C# 如何获得两个数据表之间的差异

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15002623/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 13:44:31  来源:igfitidea点击:

How to get difference between two DataTables

c#linqdatatable

提问by user2095405

I have these two datatables and I want to get the difference between them. Here is an example:

我有这两个数据表,我想了解它们之间的区别。下面是一个例子:

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

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

I just want the result as data which is in table1 and not in table2 (table1-table2)

我只想要结果作为表 1 中而不是表 2 中的数据(表 1-表 2)

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

I tried to use these two similar solutions via Linq, but it always return table1 and not table1-table2. Here is first solution:

我试图通过 Linq 使用这两个类似的解决方案,但它总是返回 table1 而不是 table1-table2。这是第一个解决方案:

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

Second solution:

第二种解决方案:

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

So, where is the mistake? Thank you a lot for all your answers. :)

那么,错误在哪里呢?非常感谢您的所有回答。:)

回答by Amol Kolekar

You can try the following code...

你可以试试下面的代码...

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

回答by SKJ

I will try to do it on a column level rather than a DataTable.

我将尝试在列级别而不是 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);

Just adding a .Select()to your answer...

只需.Select()在您的答案中添加一个...

回答by Ryszard D?egan

Try the below approach:

尝试以下方法:

Initialization:

初始化:

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

Above solution also works when there are new rows in table2 that were not present in table1.

当 table2 中有 table1 中不存在的新行时,上述解决方案也适用。

distintTableconstains Cand D.

distintTable包含CD

回答by TGarrett

Try below, this is pretty basic. Merge two sets together, and get the difference. If the sets dont align up properly, then this will not work.

试试下面,这是非常基本的。将两组合并在一起,并得到差异。如果集合没有正确对齐,那么这将不起作用。

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

回答by Kevin.Hardy

I just went through this and wanted to share my findings. For my application it is a data sync mechanism, but i think you will see how this applies to the original question.

我刚刚经历了这个,想分享我的发现。对于我的应用程序,它是一种数据同步机制,但我想您会看到这如何适用于原始问题。

In my case, I had a DataTablethat represented my lastdata upload and sometime in the future, I need to get the currentstate of the data and only upload the differences.

就我而言,我有一个DataTable代表我上次上传数据的 ,并且在将来的某个时候,我需要获取数据的当前状态并且只上传差异。

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

I hope this helps. I fought with this for a few hours, and found lots of false-leads on the interwebz, and ended up comparing RowStatesafter merging a few different ways

我希望这有帮助。我用这个打了几个小时,在interwebz上发现了很多错误的线索,最后RowStates合并了几种不同的方法后进行了比较

回答by Madhu

Try this

尝试这个

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

回答by user6826239

Try below, this is pretty basic. Merge two sets together, and get the difference. If the sets dont align up properly, then this will not work. Trying to Test the same

试试下面,这是非常基本的。将两组合并在一起,并得到差异。如果集合没有正确对齐,那么这将不起作用。尝试测试相同

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

回答by Amit Mohanty

Try This ...

    public DataTable getDiffRecords(DataTable dtDataOne, DataTable dtDataTwo)
    {
        DataTable returnTable = new DataTable("returnTable");

        using (DataSet ds = new DataSet())
        {
            ds.Tables.AddRange(new DataTable[] { dtDataOne.Copy(), dtDataTwo.Copy() });

            DataColumn[] firstColumns = new DataColumn[ds.Tables[0].Columns.Count];
            for (int i = 0; i < firstColumns.Length; i++)
            {
                firstColumns[i] = ds.Tables[0].Columns[i];
            }

            DataColumn[] secondColumns = new DataColumn[ds.Tables[1].Columns.Count];
            for (int i = 0; i < secondColumns.Length; i++)
            {
                secondColumns[i] = ds.Tables[1].Columns[i];
            }

            DataRelation r1 = new DataRelation(string.Empty, firstColumns, secondColumns, false);
            ds.Relations.Add(r1);

            DataRelation r2 = new DataRelation(string.Empty, secondColumns, firstColumns, false);
            ds.Relations.Add(r2);

            for (int i = 0; i < dtDataOne.Columns.Count; i++)
            {
                returnTable.Columns.Add(dtDataOne.Columns[i].ColumnName, dtDataOne.Columns[i].DataType);
            }

            returnTable.BeginLoadData();
            foreach (DataRow parentrow in ds.Tables[0].Rows)
            {
                DataRow[] childrows = parentrow.GetChildRows(r1);
                if (childrows == null || childrows.Length == 0)
                    returnTable.LoadDataRow(parentrow.ItemArray, true);
            }

            foreach (DataRow parentrow in ds.Tables[1].Rows)
            {
                DataRow[] childrows = parentrow.GetChildRows(r2);
                if (childrows == null || childrows.Length == 0)
                    returnTable.LoadDataRow(parentrow.ItemArray, true);
            }
            returnTable.EndLoadData();
        }
        return returnTable;
    }