2012-12-27 13 views
9

Piszę krótki algorytm, który musi porównać dwa zestawy danych, aby różnice między nimi mogły być dalej przetwarzane. Próbowałem osiągnąć ten cel, łącząc te dwa zestawy danych i uzyskać uzyskane zmiany w nowym zestawie danych.pobierz różnice w 2 zestawach danych C#

Moja metoda wygląda następująco:

private DataSet ComputateDiff(DataSet newVersion, DataSet oldVersion) 
    { 
     DataSet diff = null; 
     oldVersion.Merge(newVersion); 
     bool foundChanges = oldVersion.HasChanges(); 
     if (foundChanges) 
     { 
      diff = oldVersion.GetChanges(); 
     } 
     return diff; 
    } 

Wynik foundChanges jest zawsze fałszywe, choć oba zbiory danych mają różne wartości w nim. Oba zestawy danych mają tę samą strukturę. Składają się z trzech tabel danych, które są wynikiem trzech zapytań w bazie danych. Połączenie działa bez problemu.

Moje pytanie brzmi: Czy istnieją jakieś rozsądne wytłumaczenie dlaczego zmienna foundChanges zawsze jest fałszywe, a jeśli nie będzie LINQ zapewnić prawidłowe rozwiązanie tego problemu, czy muszę określić zmiany, iteracja zbiorów danych

Oto kilka dalszych informacji: Język programowania to C# Używam .Net framework 4.0 Pracuję na komputerze z Windows 8 Dane, jak wspomniano, pochodzi z bazy danych (MSSQL Server 2012 express) Moje DataSets lub DataTables przystań Dostałem wszystkie PK, o ile wiem.

Dzięki z góry

+1

Zwykle należy wykonać zestaw danych oldVersion i zmodyfikować go. Następnie oldVersion zawierałaby wszystkie nowe zmiany. Można wtedy wywołać DataSet diff = oldVersion.GetChanges(). –

+1

Może się okazać, że jest to przydatne: http://stackoverflow.com/a/7518025/211627 – JDB

Odpowiedz

3

Myślę, że problemem jest to, że nie rozumieją DataSetów .NET. DataTable zachowuje "oryginalną" kopię każdej załadowanej do niej wartości. Po zmianie wartości DataTable jest w stanie wykryć zmianę. Podobnie DataTable śledzi wiersze, które zostały dodane lub usunięte. Funkcja HasChanges() prostu indeksuje przez DataTables i sprawdza, czy nie było żadnych zmian (zmiana wartości, nowe wiersze, usunięte wiersze, etc.)

można znaleźć w dokumentacji MSDN:
http://msdn.microsoft.com/en-us/library/system.data.dataset.haschanges.aspx

porównywaniu dwóch zestawach danych jest podchwytliwe i nie jestem świadomy żadnej wbudowanej funkcji, aby sobie z tym poradzić (ponieważ każdy programista będzie miał własną definicję "równoważności").

Patrz:

Poniższy kod będzie porównanie dwóch DataTables szukając dodanych/usuniętych wierszy opartych na kolumnie Key i zmodyfikowane wiersze przez porównywanie wartości pasujących wierszy (ponownie, w zależności od klucza). Byłoby dość trywialne, aby rozszerzyć to w celu porównania zestawów danych (poprzez porównywanie tablic o podobnych nazwach między zestawami danych).

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 

namespace DataSetComparison 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      var l_table1 = new DataTable(); 
      l_table1.Columns.Add("Key", typeof(int)); 
      l_table1.Columns.Add("Name", typeof(string)); 
      l_table1.Columns.Add("Age", typeof(int)); 

      var l_table2 = new DataTable(); 
      l_table2.Columns.Add("Key", typeof(int)); 
      l_table2.Columns.Add("Name", typeof(string)); 
      l_table2.Columns.Add("Age", typeof(int)); 

      l_table1.Rows.Add(l_table1.NewRow()); 
      l_table1.Rows[l_table1.Rows.Count - 1]["Key"] = 0; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Name"] = "Alfred Harisson"; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Age"] = 36; 
      l_table1.Rows.Add(l_table1.NewRow()); 
      l_table1.Rows[l_table1.Rows.Count - 1]["Key"] = 1; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Name"] = "Matthew George"; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Age"] = 41; 
      l_table1.Rows.Add(l_table1.NewRow()); 
      l_table1.Rows[l_table1.Rows.Count - 1]["Key"] = 2; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Name"] = "Franklin Henry"; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Age"] = 33; 

      l_table2.Rows.Add(l_table2.NewRow()); 
      l_table2.Rows[l_table2.Rows.Count - 1]["Key"] = 0; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Name"] = "Alfred Harisson"; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Age"] = 36; 
      l_table2.Rows.Add(l_table2.NewRow()); 
      l_table2.Rows[l_table2.Rows.Count - 1]["Key"] = 1; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Name"] = "Matthew George"; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Age"] = 42; // Record 1 "modified" 
      // Record 2 "deleted" 
      // Record 3 "added": 
      l_table2.Rows.Add(l_table2.NewRow()); 
      l_table2.Rows[l_table2.Rows.Count - 1]["Key"] = 3; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Name"] = "Lester Kulick"; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Age"] = 33; 

      // Using table 1 as the control, find changes in table 2 

      // Find deleted rows: 
      var l_table2Keys = l_table2.Select().Select((r) => (int) r["Key"]); 
      var l_deletedRows = l_table1.Select().Where((r) => !l_table2Keys.Contains((int) r["Key"])); 

      foreach (var l_deletedRow in l_deletedRows) 
       Console.WriteLine("Record " + l_deletedRow["Key"].ToString() + " was deleted from table 2."); 

      // Find added rows: 
      var l_table1Keys = l_table1.Select().Select((r) => (int) r["Key"]); 
      var l_addedRows = l_table2.Select().Where((r) => !l_table1Keys.Contains((int) r["Key"])); 

      foreach (var l_addedRow in l_addedRows) 
       Console.WriteLine("Record " + l_addedRow["Key"].ToString() + " was added to table 2."); 

      // Find modified rows: 
      var l_modifiedRows = l_table2.Select() 
             .Join(
              l_table1.Select(), 
              r => (int) r["Key"], 
              r => (int) r["Key"], 
              (r1, r2) => new 
               { 
                Row1 = r1, 
                Row2 = r2 
               }) 
             .Where(
              values => !(values.Row1["Name"].Equals(values.Row2["Name"]) && 
                 values.Row1["Age"].Equals(values.Row2["Age"]))) 
             .Select(values => values.Row2); 

      foreach (var l_modifiedRow in l_modifiedRows) 
       Console.WriteLine("Record " + l_modifiedRow["Key"].ToString() + " was modified in table 2."); 

      Console.WriteLine("Press any key to quit..."); 
      Console.ReadKey(true); 

     } 
    } 
} 

wyjście konsoli:

Rekord 2 został usunięty z tabeli 2.
Zapis 3 dodano w tabeli 2.
zapisu 1 został zmodyfikowany w tabeli 2.

+0

Poszukując .contains, .exists może ci się przydać. –

+0

Cyborgx37 ma rację, nie można tego łatwo zrobić. Musiałbyś znać klucze zestawu danych, w przeciwnym razie nie byłbyś w stanie stwierdzić, czy zmiana jest aktualizacją, usunięciem czy wstawką. –

0

Jeśli schematu z obu zestawów danych są takie same wtedy można spróbować poniżej jednej

Dataset dsTest1 
DataSet dsTest2 
DataSet dsFinal; 
dsFinal.Merge(dsTest1); 
dsFinal.AcceptChanges(); 
dsFinal.Merge(dsTest2); 
DifferenceDataSet = dsFinal.GetChanges() 

Jeśli schemat obu zestawów danych są różne wtedy musisz ręcznie zrobić.

+0

Dlaczego ciągle widzę ludzi mówiących, że Merge + GetChanges działa, a kiedy nie? –

-1

Jak widać z niektórych innych odpowiedzi, nie jest łatwo uzyskać różnicę dwóch zestawów danych.

Jest to celem DataSet.GetChanges(). Jeśli rozpoczynasz od zestawu danych i wprowadzasz zmiany bezpośrednio do tego zestawu danych (tj. Gdy użytkownik aktualizuje komórkę, gdy użytkownik przesyła formularz, itd.), To DataSet śledzi zmiany. W ten sposób możesz wywołać funkcję DataSet.GetChanges(), aby uzyskać zmiany (lub różnice). Następnie możesz przetworzyć tylko zmiany.

Trudno jest pobrać początkowy zestaw danych i ostateczny zestaw danych i uzyskać różnice. Również łączenie końcowego zestawu danych ze starym zestawem danych nie ma sensu, ponieważ ostateczny zestaw danych jest wynikiem scalenia.