sql >> Database >  >> RDS >> Mysql

Flattern kind/ouder data met onbekend aantal kolommen

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.




  1. Google Spreadsheets verbinden met MySQL met JDBC

  2. mysql-query:SELECT DISTINCT column1, GROUP BY column2

  3. Biedt de mysql CLI-tool een manier om binaire gegevens op een consolevriendelijke manier weer te geven?

  4. Selecteer meerdere tabellen wanneer één tabel leeg is in MySQL