Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Płaskie dane dziecka/rodzica z nieznaną liczbą kolumn

Po wielu dniach pracy nad tym udało mi się sam rozwiązać ten problem. To, co zrobiłem, było następujące;

W mojej oryginalnej klasie potomnej MemberCode i ElementCode tworzą unikalny klucz, który zasadniczo określa nazwę kolumny. Poszedłem więc o krok dalej i dodałem „Nazwa_kolumny”, aby mieć

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; }
}

Było to oczywiście odzwierciedlone również w mojej tabeli bazy danych.

Mój SQL do wyodrębnienia danych wyglądał wtedy tak;

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

zamówienie najpierw według UniqueID ma kluczowe znaczenie dla zapewnienia, że ​​rekordy są we właściwej kolejności do późniejszego przetwarzania.

Użyłbym dynamic i ExpandoObject() do przechowywania danych.

Więc iteruję wynik, aby przekonwertować wynik sql na tę strukturę w następujący sposób;

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

Następnie moje informacje są przechowywane dynamicznie w płaski sposób, którego wymagałem.

Teraz następnym problemem był ObjectListView, którego chciałem użyć. To nie mogło zaakceptować takich dynamicznych typów.

Miałem więc informacje przechowywane w moim kodzie tak, jak chciałem, ale nadal nie mogłem ich wyświetlić zgodnie z wymaganiami.

Rozwiązaniem było użycie wariantu ObjectListView znany jako DataListView . Jest to w rzeczywistości ta sama kontrola, ale może być powiązana z danymi. Inną alternatywą byłoby również użycie DatagridView, ale chciałem trzymać się ObjectListView z innych powodów.

Więc teraz musiałem przekonwertować moje dynamiczne dane na źródło danych. Zrobiłem to w następujący sposób;

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);
}

Następnie po prostu przypisuję moje źródło danych do DataListView, generuję kolumny i hej presto, mam teraz wyodrębnione, spłaszczone i wyświetlone tak jak potrzebuję moje dane dynamiczne.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysql wstawiaj do tabeli, jeśli istnieje

  2. MySQL wybierz DISTINCT według najwyższej wartości

  3. AngularJS | Jak wysłać dane Json do bazy danych w Codeigniter

  4. Przechowywanie nadmiarowych kluczy obcych w celu uniknięcia złączeń

  5. Python Pandas - Używanie to_sql do pisania dużych ramek danych w kawałkach