2017-10-07 4 views
0

Das Problem: nur Zeilen einfügen , wenn der Primärschlüssel größer als der vorhandene beim Zusammenführen von Quell-DataTable mit tatsächlichen DataTable (ActualDT.Merge(SourceDT)).Wie füllt man DataTable-Zeilen nur, wenn der Primärschlüssel größer als der letzte Primärschlüssel ist?

Details von meinem Problem unter:

Ich fülle eine tatsächliche Datentabelle mit einem Int64 Primärschlüssel von der API von einem externen Server nach JSON Quelle Datatable Deserialisieren. Dann schreibe ich Zeilen von DataTable in meine Datenbank und bereinige alle Zeilen in DataTable mit Ausnahme des größten Primärschlüssels. Später fordere ich neue Daten von der API und oft enthält die Antwort die gleichen Zeilen, die ich bereits in die Datenbank geschrieben und von meiner DataTable bereinigt habe.

Wenn ich die DataTable-Zeilen nicht bereinigen, sinkt die Leistung und es ist Speicher Schwein. Also hinterlasse ich eine Zeile mit dem größten Primärschlüssel nach der Reinigung.

Ich möchte nicht jeden PrimaryKey von Source DataTable vor dem Zusammenführen vergleichen, Vergleich kann viel Zeit in Anspruch nehmen.

Was kann ich tun, um das Zusammenführen von Zeilen zu verhindern, die ich bereits in die Datenbank geschrieben und aus der tatsächlichen DataTable entfernt habe? Vielleicht kann ich sie sogar beim Deserialisierungsprozess ausschließen (ich benutze NewtonSoft JSON.net)? Oder einen schnellen Weg, um das Zusammenführen von Zeilen zu verhindern, wenn sie Primärschlüssel < Primärschlüssel in Actual DataTable?

Vielen Dank für Ihre Antworten!

UPDATE: Fusion Code

public class MyData 
{ 
    DataTable BlackPairs = new DataTable(); 
    DataTable WhiteTable = new DataTable(); 

    public string _Json { 

     set 
     { 
      DataSet TempDS = JsonConvert.DeserializeObject<DataSet>(value); 
      try 
      { 
       foreach (DataTable table in TempDS.Tables) 
       { 
        BlackPairs = table.Copy(); 
        WhiteTable.Merge(BlackPairs); 
       } 
      }catch{} 
     } 
    } 

    public MyData() 
    { //columns initialization 
     WhiteTable.Columns.AddRange(new DataColumn[]{columns); 
     WhiteTable.PrimaryKey = new DataColumn[]{tid}; 
    } 
+0

Können Sie 'merge function' Code posten. Sie können das darin machen –

+0

@AleksaRistic, ich habe Update-Post mit Beispiel –

+0

Notwendigkeit 'merge Funktion' Code –

Antwort

0

Ich habe benutzerdefinierte Merge Funktion erstellt basierend auf, was wir durch Kommentare gesprochen haben. Diese Funktion ist nur dann, wenn primäre Spalte typeof(int) ist, aber es kann leicht alle Arten erhalten verbessert werden oder es einfach zu ändern, welche Art Sie benötigen (string, int, bool ...)

public Test() 
{ 
    InitializeComponent(); 
    DataTable smallerDatatable = new DataTable(); 
    smallerDatatable.Columns.Add("Col1", typeof(int)); 
    smallerDatatable.Columns.Add("Col2", typeof(string)); 

    DataTable biggerDatatable = new DataTable(); 
    biggerDatatable.Columns.Add("Col1", typeof(int)); 
    biggerDatatable.Columns.Add("Col2", typeof(string)); 

    smallerDatatable.Rows.Add(1, "Row1"); 
    smallerDatatable.Rows.Add(2, "Row2"); 
    smallerDatatable.Rows.Add(3, "Row3"); 
    biggerDatatable.Rows.Add(1, "Row1"); 
    biggerDatatable.Rows.Add(2, "Row2"); 
    biggerDatatable.Rows.Add(3, "Row3"); 
    biggerDatatable.Rows.Add(4, "Row4"); 
    biggerDatatable.Rows.Add(5, "Row5"); 

    DataTable mergedTable = MergeOnUniqueColumn(smallerDatatable, biggerDatatable, "Col1"); 
    dataGridView1.DataSource = mergedTable; 
} 

private DataTable MergeOnUniqueColumn(DataTable smallTable, DataTable bigTable, string uniqueColumn) 
{ 
    DataTable m = smallTable; 
    for(int i = 0; i < bigTable.Rows.Count; i++) 
    { 
     if(!(smallTable.AsEnumerable().Any(row => bigTable.Rows[i][uniqueColumn].Equals(row.Field<object>(uniqueColumn))))) 
     { 
      smallTable.Rows.Add(bigTable.Rows[i].ItemArray); 
     } 
    } 
    return m; 
} 

Funktion über jedes füllen fehlender eindeutiger Wert innerhalb smallTable von bigTable.

Wenn Sie smallTable mit Werten von bigTable nur nach der letzten smallTable Zeile füllen möchten, verwenden Sie diese Funktion.

private DataTable MergeOnUniqueColumnAfterLastID(DataTable smallTable, DataTable bigTable, string uniqueColumn) 
{ 
    DataTable m = smallTable; 
    int maxUnique = Convert.ToInt32(m.Compute("max([" + uniqueColumn + "])", string.Empty)); 
    for (int i = 0; i < bigTable.Rows.Count; i++) 
    { 
     if (!(smallTable.AsEnumerable().Any(row => (int)bigTable.Rows[i][uniqueColumn] <= maxUnique))) 
     { 
      smallTable.Rows.Add(bigTable.Rows[i].ItemArray); 
     } 
    } 
    return m; 
} 
+0

wenn 'smallingDataTable' nicht existiert Row1 und Row2, es ist immer noch verbinden Row1 und Row2 zu' smallereDataTable' von 'biggerDataTable'. Ich schaue zippy Weg, um Row1 und Row2 von kleinerenDataTable zu säubern und Zeilen von 'biggerDataTable' nur nach Row3 einzufügen. –

+0

Wenn ich es bekomme, möchten Sie nicht nur einfügen, wenn 'uniqueColumn' Wert in' smallTable' nicht existiert, aber nur wenn es größer ist als 'smallTable max uniqueColumn Wert'? –

+0

@ Иванпогосов Ich habe Antwort bearbeitet und neue Funktion hinzugefügt, die Sie anstelle der alten verwenden werden –

Verwandte Themen