Laden...

DataTable.Merge: Tabellen aus DataSet mergen anhand von Fremdschlüsselbeziehungen

Erstellt von inflames2k vor 4 Jahren Letzter Beitrag vor 4 Jahren 795 Views
inflames2k Themenstarter:in
2.298 Beiträge seit 2010
vor 4 Jahren
DataTable.Merge: Tabellen aus DataSet mergen anhand von Fremdschlüsselbeziehungen

verwendetes Datenbanksystem: System.Data.DataSet

Hallo,

für einen aktuellen Anwendungsfall lese ich Xml-Dateien in ein DataSet ein. Da es hier durchaus auch verschachtelungen gibt und ich die Daten in einer Tabelle benötige wollte ich die Daten zusammen fügen.

Dazu werden durch das DataSet automatisch beim Einlesen Fremdschlüsselbeziehungen aufgebaut. Mein Gedanke war nun alle DataRelations der Tabellen durchzugehen und diese nach folgendem Prinzip zu mergen:


        private void MergeTables(DataTable dataTable)
        {
            foreach (DataRelation relation in dataTable.ChildRelations)
            {
                DataTable childTable = relation.ChildTable;
                this.MergeTables(childTable);

                dataTable.Merge(relation.ChildTable);
            }
            dataTable.AcceptChanges();
        }

Das funktioniert auch solang ich nicht zu weit verschachtele. Folgende Struktur funktioniert noch:


<?xml version="1.0" encoding="utf-16"?>
<Data>
   <Entry>
         <Type>
               <EventType>Import</EventType>
               <ImportType>-</ImportType>
         </Type>
         <Hint>DataHint</Hint>
         <Key>DataKey</Key>
   </Entry>
</Data>

Gehe ich aber bei Type noch eine Ebene tiefer funktioniert das ganze nicht mehr. Es wird eine unspezifizierte NullReference Exception geworfen.

Beispiel Xml:


<?xml version="1.0" encoding="utf-16"?>
<Data>
   <Entry>
         <Type>
               <EventType>Import</EventType>
               <ImportType>-</ImportType>
               <State>
                    <Valid>false</Valid>
                    <Error>some error</Error>
               </State>
         </Type>
         <Hint>DataHint</Hint>
         <Key>DataKey</Key>
   </Entry>
</Data>

Hat jemand eine Idee, wie ich das Problem lösen kann und die Daten in eine DataTable gemerged bekomme, auch bei höheren Verschachtelungstiefen?

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

inflames2k Themenstarter:in
2.298 Beiträge seit 2010
vor 4 Jahren

Ich bin hier nun einen anderen Weg gegangen. Der für mich wesentlich einfacher umzusetzen war.

Statt die Tabellen zu Mergen, werden bei der Verarbeitung die Relations durchgegangen und die Spalten aus den ChildTabellen verarbeitet.

Falls dennoch jemand eine Idee für den beschriebenen Fall hat wäre ich dafür natürlich noch offen. Der jetzige Weg funktioniert allerdings auch ganz gut.

// EDIT: Noch ein paar Details mehr zu meiner Lösung.

Benötigt habe ich das oben beschriebene um verschiedenste Eingangsdaten (DataTable aus Datenbank, XmlDokument und Csv-Datenquellen) in eine konfigurierbare Csv-Struktur zu exportieren.
Der einfachhalt wegen bin ich dann den naiven Weg gegangen, dass ich mir gesagt habe, dass kann man alles in DataTables / DataSets einlesen. Eine Csv-Datei als Quelle ist ja schließlich auch nichts anderes als eine Tabelle.

Problem bereitete mir dann allerdings die Ermittlung der Xml-Knoten bei geschachtelten Xml-Dateien. Dazu habe ich mich dann erst einmal 3 Stunden darin verrannt die Tabellen zu mergen.

Am Ende bin ich dann doch den Weg gegangen, dass ich die DataRelations ausgewertet habe.

Aufbau der Datenermittlung war dann wie folgt:


foreach(DataRow row in sourceTable.Rows)
{
     for(int i = 0; i < this.SourceColumns.Count; i++)
     {

          if (i > 0)
             stringBuilder.Append(delimiter);

         string sourceColumn = this.SourceColumns[i];

         if(!sourceColumn.Contains("\\") && !sourceColumn.Contains("/")
         {
              stringBuilder.Append(rows[sourceColumn].ToString());
         }
         else
         {
              string[] tablePathParts = sourceColumn.Split(new char[] { '\\', '/' });
              DataRow[] relationalRows = row.GetChildRows($"{sourceTable.TableName}_{tablePathParts[0]}");
              if(relationalRows.Count > 1)
                 throw new ArgumentException($"Mapping not valid. Multiple entries for {sourceColumn} found.");
              else
                  stringBuilder.Append(relationalRows[0][tablePathParts[1]].ToString());
         }   
     }

     stringBuilder.AppendLine();      
}

Natürlich ist noch mehr Fehlerbehandlung enthalten. Aber im groben und ganzen löste das meine ganzen Probleme.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |