Na vele, vele dagen hieraan te hebben gewerkt, heb ik dit probleem zelf kunnen oplossen. Wat ik deed was het volgende;
In mijn oorspronkelijke kindklasse maken de MemberCode en ElementCode een unieke sleutel die in feite aangeeft wat de kolomnaam was. Dus ik ging nog een stap verder en voegde een "Column_Name" toe zodat ik
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; }
}
Dit werd duidelijk ook weerspiegeld in mijn databasetabel.
Mijn SQL om de gegevens te extraheren zag er toen zo uit;
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
eerst bestellen met de UniqueID is van cruciaal belang om ervoor te zorgen dat de records in de juiste volgorde staan voor latere verwerking.
Ik zou een dynamic
. gebruiken en een ExpandoObject()
om de gegevens op te slaan.
Dus ik herhaal het resultaat om het sql-resultaat als volgt in deze structuur om te zetten;
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
Dan heb ik mijn informatie dynamisch opgeslagen op de platte manier die ik nodig had.
Het volgende probleem was de ObjectListView die ik wilde gebruiken. Dit kan dergelijke dynamische typen niet accepteren.
Dus ik had de informatie in mijn code opgeslagen zoals ik wilde, maar ik kon het nog steeds niet weergeven zoals nodig was.
De oplossing was om een variant van de ObjectListView
. te gebruiken bekend als de DataListView
. Dit is in feite hetzelfde besturingselement, maar kan gegevensgebonden zijn. Een ander alternatief zou ook zijn om een DatagridView te gebruiken, maar ik wilde om andere redenen bij de ObjectListView blijven.
Dus nu moest ik mijn dynamische data omzetten naar een Datasource. Dit heb ik als volgt gedaan;
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);
}
Dan wijs ik eenvoudig mijn gegevensbron toe aan de DataListView, genereer de kolommen, en hey presto ik heb nu mijn dynamische gegevens geëxtraheerd, afgevlakt en weergegeven zoals ik nodig heb.