2012-12-27 9 views
9

Sto scrivendo un breve algoritmo che deve confrontare due DataSet, in modo che le differenze tra entrambi possano essere ulteriormente elaborate. Ho provato a raggiungere questo obiettivo unendo questi due DataSet e ottenere le modifiche risultanti in un nuovo DataSet.ottenere le differenze in 2 DataSet C#

Il mio metodo è simile al seguente:

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

Il risultato di foundChanges è sempre falso, anche se i due set di dati hanno valori diversi in esso. Entrambi i set di dati hanno la stessa trama. Consistono in tre DataTable che sono il risultato di tre query in un database. L'unione funziona correttamente senza problemi.

La mia domanda è: C'è qualche spiegazione ragionevole motivo per cui la variabile foundChanges è sempre false e se non Linq fornire una soluzione adeguata a questo problema o devo per determinare i cambiamenti scorrendo i dataset

Ecco alcune ulteriori informazioni: Il linguaggio di programmazione è C# Sto usando .Net framework 4.0 Sto sviluppando su una macchina Windows 8 I dati come menzionati provengono da un database (MSSQL Server 2012 express) My DataSets o DataTables rifugio Ho qualche PK per quanto ne so.

Grazie in anticipo

+1

In genere ciò che si dovrebbe fare è prendere un dataset oldVersion e modificarlo. Allora oldVersion conterrà tutte le nuove modifiche. È quindi possibile chiamare DataSet diff = oldVersion.GetChanges(). –

+1

Potresti trovare questo utile: http://stackoverflow.com/a/7518025/211627 – JDB

risposta

3

Credo che il problema è che non si capisce DataSet .NET. Un DataTable conserva la copia "originale" di ogni valore caricato in esso. Quando viene modificato un valore, DataTable è in grado di rilevare la modifica. Allo stesso modo, DataTable tiene traccia delle righe che sono state aggiunte o eliminate. La funzione HasChanges() striscia semplicemente attraverso le DataTable e controlli per vedere se c'è stata alcuna modifica (valore modificato, nuove righe, righe eliminate, ecc)

Vedere la documentazione MSDN:
http://msdn.microsoft.com/en-us/library/system.data.dataset.haschanges.aspx

Confrontando due set di dati è difficile, e non sono a conoscenza di alcuna funzione incorporata per gestirlo (poiché ogni programmatore avrà la propria definizione di "equivalenza").

See:

Il codice qui sotto vi confrontare le due DataTable, cercando di aggiungere le righe/cancellati sulla base di una colonna chiave e modificati righe confrontando i valori delle righe corrispondenti (di nuovo, in base alla chiave). Sarebbe piuttosto banale espanderlo per confrontare i DataSet (confrontando tabelle con nomi simili tra DataSet).

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

     } 
    } 
} 

uscita della console:

Record 2 è stato eliminato dalla tabella 2.
Record 3 è stato aggiunto al tavolo 2.
Notizia 1 è stato modificato nella tabella 2.

+0

Solo nell'esaminare .contains, .exists potrebbe esserti utile. –

+0

Cyborgx37 ha ragione non è possibile farlo facilmente. Dovresti avere la conoscenza delle chiavi del set di dati, altrimenti non sarai in grado di dire se una modifica è un aggiornamento, una cancellazione o un inserimento. –

0

Se lo schema dei dataset entrambi sono gli stessi, allora si può provare di sotto di un

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

Se lo schema di entrambi i set di dati sono diversi, allora si deve fare manualmente.

+0

Perché continuo a vedere le persone che dicono che Merge + GetChanges funziona, quando non funziona? –

-1

Come si può vedere da alcune delle altre risposte, non è facile ottenere la differenza di due DataSet.

Questo è lo scopo di DataSet.GetChanges(). Se si inizia con un set di dati e si apportano modifiche direttamente a tale set di dati (ad esempio quando un utente aggiorna una cella, quando un utente invia un modulo, ecc.), Il DataSet tiene traccia delle modifiche. In questo modo è possibile chiamare DataSet.GetChanges() per ottenere le modifiche (o la differenza). È quindi possibile elaborare solo le modifiche.

È un problema difficile prendere un dataset iniziale e un set di dati finale e ottenere le differenze. Anche fondere il dataset finale con il dataset precedente non ha senso, poiché il set di dati finale è il risultato dell'unione.