【问题标题】:How to get difference between two DataTables如何获得两个数据表之间的差异
【发布时间】:2013-02-21 12:46:25
【问题描述】:

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

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

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

我只想将结果作为 table1 中的数据而不是 table2 (table1-table2) 中的数据

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

我尝试通过 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);

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

【问题讨论】:

  • 除了检查它们是否是同一个实例。它们各自的属性是否相同。您可以使用接受 EqualityComparer 的重载,也可以研究在各种 LINQ+ 库中实现的扩展方法 exceptBy(),也在 Jon Skeets MoreLinq (code.google.com/p/morelinq) 中实现
  • @Tormod,但是在他的第一个解决方案中DataRowComparer 的用途是什么?它会覆盖public bool Equals(TRow leftRow, TRow rightRow) 来比较实际的列值。
  • 您能展示一下您是如何检索数据表的吗?数据是否可能与您预期的不同?我在 LINQPad 中做了一个快速示例,您的第一个解决方案似乎工作正常。
  • @Tormod,msdn 库另有说明:DataRowComparer 类用于比较 DataRow 对象的值,不比较对象引用。 (msdn.microsoft.com/en-us/library/…)

标签: c# linq datatable


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    在我的例子中,我有一个 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);
    

    我希望这会有所帮助。我为此奋斗了几个小时,在interwebz上发现了很多假线索,最后在合并了几种不同的方式后比较了RowStates

    【讨论】:

    • 当我尝试这个时,我从 GetChanges 中得到的只是集合的并集,而不是差异。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      试试这个

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

      【讨论】:

      • “试试这个”并不是真正的答案。
      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

        试试下面的方法:

        初始化:

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

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

        distintTable 包含 CD

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:
            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;
                }
            

            【讨论】:

            • “试试这个”并不是真正的答案。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-10-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多