2013-02-21 13 views
20

Ho questi due datatables e voglio ottenere la differenza tra loro. Ecco un esempio:Come ottenere la differenza tra due DataTable

Table1 
------------------------- 
ID | Name 
-------------------------- 
1 | A 
2 | B 
3 | C 
-------------------------- 

Table2 
------------------------- 
ID | Name 
-------------------------- 
1 | A 
2 | B 
-------------------------- 

Voglio solo il risultato come dati che è in tabella 1 e non a table2 (tabella 1-tabella2)

ResultTable 
------------------------- 
ID | Name 
-------------------------- 
3 | C 
-------------------------- 

Ho cercato di usare queste due soluzioni simili via Linq, ma restituisce sempre table1 e non table1-table2. Qui è la prima soluzione:

DataTable table1= ds.Tables["table1"]; 
DataTable table2= ds.Tables["table2"]; 
var diff= table1.AsEnumerable().Except(table2.AsEnumerable(),DataRowComparer.Default); 

Seconda soluzione:

var dtOne = table1.AsEnumerable(); 
var dtTwo = table2.AsEnumerable(); 
var difference = dtOne.Except(dtTwo); 

Allora, dov'è l'errore? Grazie mille per tutte le tue risposte. :)

+2

Tranne controlla se sono o meno la stessa istanza. Non se le loro rispettive proprietà sono identiche. Puoi utilizzare il sovraccarico che accetta un EqualityComparer oppure puoi studiare il metodo di estensione ExceptBy() implementato in varie librerie LINQ +, anche in Jon Skeets MoreLinq (http://code.google.com/p/morelinq/) – Tormod

+2

@ Tormod, ma qual è l'uso di 'DataRowComparer' nella sua prima soluzione? Sovrascrive 'public bool Equals (TRow leftRow, TRow rightRow)' per confrontare i valori effettivi delle colonne. – hometoast

+2

Puoi mostrare come stai recuperando i tuoi dati? È possibile che i dati siano diversi da come ti aspetti? Ho fatto un rapido esempio in LINQPad e la tua prima soluzione sembra funzionare correttamente. – goric

risposta

7

È possibile provare il seguente codice ...

table1.AsEnumerable().Where(
    r =>!table2.AsEnumerable().Select(x=>x["ID"]).ToList().Contains(r["ID"])).ToList(); 
1

cercherò di farlo su un livello di colonna piuttosto che un DataTable.

IEnumerable<int> id_table1 = table1.AsEnumerable().Select(val=> (int)val["ID"]); 
IEnumerable<int> id_table2 = table2.AsEnumerable().Select(val=> (int)val["ID"]); 
IEnumerable<int> id_notinTable1= id_table2.Except(id_table1); 

Basta aggiungere un .Select() per la tua risposta ...

0

provare il metodo seguito:

inizializzazione:

var columnId = new DataColumn("ID", typeof (int)); 
var columnName = new DataColumn("Name", typeof (string)); 
var table1 = new DataTable(); 
table1.Columns.AddRange(new[] {columnId, columnName}); 
table1.PrimaryKey = new[] {columnId}; 
table1.Rows.Add(1, "A"); 
table1.Rows.Add(2, "B"); 
table1.Rows.Add(3, "C"); 

var table2 = table1.Clone(); 
table2.Rows.Add(1, "A"); 
table2.Rows.Add(2, "B"); 
table2.Rows.Add(4, "D"); 

Soluzione:

var table3 = table1.Copy(); 
table3.AcceptChanges(); 
table3.Merge(table2); 

var distinctRows = from row in table3.AsEnumerable() 
        where row.RowState != DataRowState.Modified 
        select row; 

var distintTable = distinctRows.CopyToDataTable(); 

Sopra soluti on funziona anche quando ci sono nuove righe in table2 che non erano presenti in table1.

distintTable constains C e D.

0

Prova di seguito, questo è piuttosto semplice. Unisci due set insieme e ottieni la differenza. Se i set non si allineano correttamente, non funzionerà.

DataSet firstDsData = new DataSet(); 
DataSet secondDsData = new DataSet(); 
DataSet finalDsData = new DataSet(); 
DataSet DifferenceDataSet = new DataSet(); 
finalDsData.Merge(firstDsData); 
finalDsData.AcceptChanges(); 
finalDsData.Merge(secondDsData); 
DifferenceDataSet = finalDsData.GetChanges(); 
5

Ho appena passato questo e ho voluto condividere le mie scoperte. Per la mia applicazione è un meccanismo di sincronizzazione dei dati, ma penso che vedrete come questo si applica alla domanda originale.

Nel mio caso, ho avuto un DataTable che rappresentava la mia ultima caricamento dei dati e in futuro, ho bisogno di ottenere lo stato corrente dei dati e caricare solo le differenze.

// get the Current state of the data 
DataTable dtCurrent = GetCurrentData(); 

// get the Last uploaded data 
DataTable dtLast = GetLastUploadData(); 
dtLast.AcceptChanges(); 

// the table meant to hold only the differences 
DataTable dtChanges = null; 

// merge the Current DataTable into the Last DataTable, 
// with preserve changes set to TRUE 
dtLast.Merge(dtCurrent, true); 

// invoke GetChanges() with DataRowState.Unchanged 
// !! this is the key !! 
// the rows with RowState == DataRowState.Unchanged 
// are the differences between the 2 tables 
dtChanges = dtLast.GetChanges(DataRowState.Unchanged); 

Spero che questo aiuti.Ho combattuto con questo per un paio d'ore, e ho trovato un sacco di falsi-porta sul interwebz, e ha finito per il confronto RowStates dopo la fusione diversi modi

+0

Quando provo tutto questo, esco da GetChanges è l'unione dei set, non la differenza. –

1

Prova questo

DataTable dtmismatch = Table1.AsEnumerable().Except(Table2.AsEnumerable(), DataRowComparer.Default).CopyToDataTable<DataRow>(); 
1

Prova di sotto, questo è abbastanza di base. Unisci due set insieme e ottieni la differenza. Se i set non si allineano correttamente, non funzionerà. mettermi alla prova lo stesso

DataSet firstDsData = new DataSet(); 
DataSet secondDsData = new DataSet(); 
DataSet finalDsData = new DataSet(); 
DataSet DifferenceDataSet = new DataSet(); 
finalDsData.Merge(firstDsData); 
finalDsData.AcceptChanges(); 
finalDsData.Merge(secondDsData); 
DifferenceDataSet = finalDsData.GetChanges();