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

C# 如何获得两个数据表之间的差异,c#,linq,datatable,C#,Linq,Datatable,我有这两个数据表,我想知道它们之间的区别。以下是一个例子: Table1 ------------------------- ID | Name -------------------------- 1 | A 2 | B 3 | C -------------------------- Table2 ------------------------- ID | Name -------------------------- 1 | A 2 | B

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

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

Table2
-------------------------
ID  |   Name 
--------------------------
 1  |  A
 2  |  B
--------------------------
我只希望结果是表1中的数据,而不是表2中的数据(表1-2)

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

DataTable table1= ds.Tables["table1"];
DataTable table2= ds.Tables["table2"];
var diff= table1.AsEnumerable().Except(table2.AsEnumerable(),DataRowComparer.Default);
var dtOne = table1.AsEnumerable();
var dtTwo = table2.AsEnumerable();
var difference = dtOne.Except(dtTwo);
第二种解决方案:

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

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

您可以尝试以下代码

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

我将尝试在列级别而不是数据表级别执行此操作

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);
IEnumerable id_table1=table1.AsEnumerable().Select(val=>(int)val[“id]”);
IEnumerable id_table2=table2.AsEnumerable().Select(val=>(int)val[“id”]);
IEnumerable id\u notinTable1=id\u表2。除(id\u表1)外;

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

尝试以下方法:

初始化:

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");
解决方案:

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();
当表2中存在表1中不存在的新行时,上述解决方案也有效


distintTable
constantsCD

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

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

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

在我的例子中,我有一个
数据表
,它代表了我上次上传的数据,在将来的某个时候,我需要获得数据的当前状态,只上传差异

//  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);
我希望这有帮助。我为此争论了几个小时,在interwebz上发现了很多虚假线索,最后在合并了几种不同的方法后比较了
行状态
,试试这个

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

试试下面,这是非常基本的。将两个集合合并在一起,得到差异。如果设置没有正确对齐,则这将不起作用。 试着测试同样的问题

试试这个。。。
公共数据表GetDiverRecords(数据表dtDataOne、数据表dtDataTwo)
{
DataTable returnTable=新的DataTable(“returnTable”);
使用(数据集ds=新数据集())
{
AddRange(新数据表[]{dtDataOne.Copy(),dtDataTwo.Copy()});
DataColumn[]firstColumns=新的DataColumn[ds.Tables[0].Columns.Count];
for(int i=0;i
除非检查它们是否为同一实例。它们各自的性质是否相同并不相同。您可以使用接受EqualityComparer的重载,也可以研究在各种LINQ+库中实现的扩展方法ExceptBy(),也可以在Jon Skeets MoreLinq()@Tormod中实现,但是在他的第一个解决方案中,
DataRowComparer
有什么用呢?它覆盖公共bool Equals(TRow leftRow,TRow rightRow)来比较实际的列值。您能说明如何检索数据表吗?数据是否可能与您预期的不同?我在LINQPad中做了一个快速示例,您的第一个解决方案似乎很好。@Tormod,msdn库则相反:DataRowComparer类用于比较DataRow对象的值,而不比较对象引用。()当我尝试这个时,我从GetChanges得到的只是集合的并集,而不是差异。“尝试这个”不是真正的答案。“尝试这个”不是真正的答案。