web-dev-qa-db-fra.com

Comment faire la différence entre deux DataTables

J'ai ces deux datatables et je veux faire la différence entre eux. Voici un exemple:

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

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

Je veux juste le résultat en tant que données qui se trouvent dans table1 et non dans table2 (table1-table2)

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

J'ai essayé d'utiliser ces deux solutions similaires via Linq, mais elle renvoie toujours table1 et non table1-table2. Voici la première solution:

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

Deuxième solution:

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

Alors, où est l'erreur? Merci beaucoup pour toutes vos réponses. :)

21
user2095405

Vous pouvez essayer le code suivant ...

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

Je viens de traverser cela et je voulais partager mes découvertes. Pour mon application, il s’agit d’un mécanisme de synchronisation des données, mais je pense que vous verrez comment cela s’applique à la question initiale.

Dans mon cas, j'avais une DataTable qui représentait mon dernier téléchargement de données et, dans le futur, je devrais obtenir le statut actuel des données et ne télécharger que les différences.

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

J'espère que ça aide. Je me suis battu avec cela pendant quelques heures, et j'ai trouvé beaucoup de fausses pistes sur interwebz, et j'ai fini par comparer RowStates après avoir fusionné plusieurs façons différentes.

5
Kevin.Hardy

Je vais essayer de le faire au niveau d'une colonne plutôt que d'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);

Il suffit d'ajouter une .Select() à votre réponse ...

1
SKJ

Essayez ci-dessous, c'est assez basique. Fusionner deux ensembles ensemble, et obtenez la différence. Si les ensembles ne s'alignent pas correctement, cela ne fonctionnera pas . Essayer de tester la même chose

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();
1
user6826239

Essaye ça

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

Essayez l'approche ci-dessous:

Initialisation:

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

Solution:

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

La solution ci-dessus fonctionne également lorsque de nouvelles lignes de la table2 ne figuraient pas dans la table1.

distintTable contientCetD.

0
Ryszard Dżegan

Essayez ci-dessous, c'est assez basique. Fusionner deux ensembles ensemble, et obtenez la différence. Si les ensembles ne s'alignent pas correctement, cela ne fonctionnera pas. 

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();
0
TGarrett