具有未知列数的Flattern子/父数据

我很难找到存储和表示我在SQL(MySQL DB)和C#窗体中的数据的最佳方法。

我的数据映射到看起来像这样的类;

public class Parent { public string UniqueID { get; set; } //Key public DateTime LoadTime { get; set; } public string Reference { get; set; } private List 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 )中显示它,但如果它让生活更轻松,可以考虑datagrid。

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

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

我的数据

但由于数据的动态性,我努力做到这一点。 在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; } } 

这显然也反映在我的数据库表中。

我的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 allRecords = new List(); //A list of all my records List 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(); //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。 这不能接受这种动态类型。

所以我根据需要将信息存储在我的代码中,但我仍然无法按需要显示它。

解决方案是使用称为DataListViewObjectListView的变体。 这实际上是相同的控制,但可以是数据绑定。 另一个替代方案也是使用DatagridView,但我想坚持使用ObjectListView出于其他原因。

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

 DataTable dt = new DataTable(); foreach (dynamic record in allRecords) { DataRow dr = dt.NewRow(); foreach (dynamic item in record) { var prop = (IDictionary)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,生成列,然后我现在将我的动态数据提取,展平并显示我的需求。