gpt4 book ai didi

c# - 展平具有未知列数的子/父数据

转载 作者:行者123 更新时间:2023-11-29 21:11:11 24 4
gpt4 key购买 nike

我正在努力寻找存储和表示 SQL (MySQL DB) 和 C# Windows 表单中的数据的最佳方法。

我的数据映射到如下所示的类;

public class Parent
{
public string UniqueID { get; set; } //Key
public DateTime LoadTime { get; set; }
public string Reference { get; set; }
private List<Child> Elements { get; set; }
}

public class Child
{
public int MemberCode { get; set; } //Composite key
public int ElementCode { get; set; } //Composite key
public Object Data { get; set; }
}

我的数据非常动态。因此父记录可以有任意数量的子记录。

在子记录中,MemberCode 和 ElementCode 实际上是其他表/类的外键,当执行查找时,它们会提供有关数据实际内容的详细信息。例如

MemberCode = 1 & ElementCode = 1 means data is a Date
MemberCode = 1 & ElementCode = 3 means data is a telephone number
MemberCode = 2 & ElementCode = 11 means data is a Product Code
MemberCode = 2 & ElementCode = 12 means data is a Service Code
etc

它们有效地组合起来指示列名是什么,并且它们始终相同(因此 MemberCode = 1 & ElementCode = 1 将始终是 Date,无论它与哪个子对象关联)。目前这些是引用/查找,但我也可以将数据放入类中的变量中,因为这可能会更容易。那么它就更像是一个键值对。

目前在我的数据库中,我将它们存储为两个表,子记录还包含来自父记录的 UniqueID。但我不确定这是否是最好的方法,正如我将解释的那样。

我的表是这样创建的

CREATE TABLE `PARENT` (
`ID` INT(11) NOT NULL AUTO_INCREMENT,
`LOADTIME` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`REFERENCE` VARCHAR(100) NOT NULL,
PRIMARY KEY (`ID`)
)

CREATE TABLE `CHILD` (
`ID` INT(11) NOT NULL,
`MEMBER_CODE` INT(11) NOT NULL,
`ELEMENT_CODE` INT(11) NOT NULL,
`DATA` VARCHAR(4000) NULL DEFAULT NULL,
PRIMARY KEY (`ID`, `MEMBER_CODE`, `ELEMENT_CODE`),
CONSTRAINT `fk_ID` FOREIGN KEY (`ID`) REFERENCES `Parent` (`ID`)
)

现在我想要做的是展平这些数据,以便我可以将单个父记录与所有子记录显示为一行。理想情况下,我希望将其显示在 ObjectListView ( http://objectlistview.sourceforge.net/cs/index.html ) 中,但如果它能让生活更轻松,可以考虑使用数据网格。

因为我的数据是动态的,所以我很难将其展平,如果我选择 10 个父记录,那么每个父记录可以有不同数量的子元素,并且每个可以有不同的 MemberCodes 和 ElementCode,这意味着它们实际上是不同的列。

所以我的数据可能如下所示(但规模更大);

My Data

但是由于数据的动态特性,我很难做到这一点。在我的代码中的 SQL 或对象中。也许还有另一种更适合它的方式来存储我的数据。

最佳答案

经过很多天的努力,我自己成功解决了这个问题。我所做的如下;

在我原来的子类中,MemberCode 和 ElementCode 生成一个唯一的键,基本上说明了列名是什么。所以我更进一步,添加了一个“Column_Name”,这样我就有了

public class Child
{
public int MemberCode { get; set; } //Composite key
public int ElementCode { get; set; } //Composite key
public string Column_Name { get; set; } //Unique. Alternative Key
public Object Data { get; set; }
}

这显然也反射(reflect)在我的数据库表中。

我的 SQL 提取数据看起来像这样;

select  p.UniqueID, p.LoadTime, p.reference, c.MemberCode, c.ElementCode , c.column_name, c.Data 
from parent as p, child as c
where p.UniqueID = c.UniqueID
//aditional filter criteria
ORDER BY p.UniqueID, MemberCode, ElementCode

首先按 UniqueID 排序对于确保记录以正确的顺序供以后处理至关重要。

我将使用 dynamicExpandoObject() 来存储数据。

因此,我迭代结果,将 sql 结果转换为此结构,如下所示;

List<dynamic> allRecords = new List<dynamic>();  //A list of all my records
List<dynamic> singleRecord = null; //A list representing just a single record

bool first = true; //Needed for execution of the first iteration only
int lastId = 0; //id of the last unique record

foreach (DataRow row in args.GetDataSet.Tables[0].Rows)
{
int newID = Convert.ToInt32(row["UniqueID"]); //get the current record unique id

if (newID != lastId) //If new record then get header/parent information
{
if (!first)
allRecords.Add(singleRecord); //store the last record
else
first = false;

//new object
singleRecord = new List<dynamic>();

//get parent information and store it
dynamic head = new ExpandoObject();
head.Column_name = "UniqueID";
head.UDS_Data = row["UniqueID"].ToString();
singleRecord.Add(head);

head = new ExpandoObject();
head.Column_name = "LoadTime";
head.UDS_Data = row["LoadTime"].ToString();
singleRecord.Add(head);

head = new ExpandoObject();
head.Column_name = "reference";
head.UDS_Data = row["reference"].ToString();
singleRecord.Add(head);
}

//get child information and store it. One row at a time
dynamic record = new ExpandoObject();

record.Column_name = row["column_name"].ToString();
record.UDS_Data = row["data"].ToString();
singleRecord.Add(record);

lastId = newID; //store the last id
}
allRecords.Add(singleRecord); //stores the last complete record

然后我以我需要的扁平方式动态存储我的信息。

现在下一个问题是我想使用的 ObjectListView。这无法接受此类动态类型。

因此,我按照需要将信息存储在代码中,但仍然无法按要求显示它。

解决方案是使用 ObjectListView 的变体,称为 DataListView。这实际上是相同的控件,但可以进行数据绑定(bind)。另一种选择也是使用 DatagridView,但由于其他原因我想坚持使用 ObjectListView。

所以现在我必须将动态数据转换为数据源。我这样做如下;

DataTable dt = new DataTable();            
foreach (dynamic record in allRecords)
{
DataRow dr = dt.NewRow();
foreach (dynamic item in record)
{
var prop = (IDictionary<String, Object>)item;
if (!dt.Columns.Contains(prop["Column_name"].ToString()))
{
dt.Columns.Add(new DataColumn(prop["Column_name"].ToString()));
}

dr[prop["Column_name"].ToString()] = prop["UDS_Data"];
}
dt.Rows.Add(dr);
}

然后,我只需将数据源分配给 DataListView,生成列,嘿,现在我已经提取、展平并显示了我需要的动态数据。

关于c# - 展平具有未知列数的子/父数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36350480/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com