【问题标题】:How to compare 2 DataTables?如何比较 2 个数据表?
【发布时间】:2012-11-30 20:47:03
【问题描述】:

我有 2 个数据表:

 DataTable OldDataTable = HttpContext.Current.Cache["oldDataTable"];

|  ID  | Value
|  1   |   0
|  2   |   0

DataTable NewDataTable =/*Get New Record Data*/

|  ID  | Value
|  1   |   0
|  2   |   1          new Value
|  3   |   0          new Row

我如何比较这两个数据表来做一些工作:

提醒并更新新值,并将新行更新为oldDataTable

然后又一个newDatatable 来了,

DataTable AnotherNewDataTable =/*Get New Record Data*/

|  ID  | Value
                          no more record in ID 1
|  2   |   1          
|  3   |   0         

oldDataTable 中删除该行。

如何保持循环并与新数据表进行比较?

【问题讨论】:

  • 看起来您正在寻找 DataTable.Merge 方法。但它不会删除丢失的行,您必须手动找到它们。
  • 看这个问题的答案:stackoverflow.com/questions/10984453/…>

标签: c#


【解决方案1】:

检查Select属性DataTable

 DataRow[] result = NewDataTable.Select("ID <> '" + OldDataTable.Columns['ID'].ToString() + "'"
                + " OR" + " Value <>'" + OldDataTable.Columns['Value'].ToString() + "'");

以上代码将两个DataTables 之间的不匹配 行存储在DataRow 数组中。这里&lt;&gt; 的意思是“不等于”。
(以上示例基于NewDataTable 的行数比OldDataTable 多的假设。)

【讨论】:

    【解决方案2】:

    尝试以下代码比较两个数据表:

    private void button1_Click(object sender, EventArgs e)   
    {      
        // Something to do with the Initialization of the FirstDataTable and SecondDataTable  
        DataTable dt;  
        dt = getDifferentRecords(FirstDataTable, SecondDataTable);  
    
        if (dt.Rows.Count == 0)  
            MessageBox.Show("Equal");  
        else 
            MessageBox.Show("Not Equal");
    }
    
    // Compare two DataTables and return a DataTable with DifferentRecords       
    /// <summary>       
    /// Compare two DataTables and return a DataTable with DifferentRecords   
    /// </summary>   
    /// <param name="FirstDataTable">FirstDataTable</param>   
    /// <param name="SecondDataTable">SecondDataTable</param>   
    /// <returns>DifferentRecords</returns>
    
    public DataTable getDifferentRecords(DataTable FirstDataTable, DataTable SecondDataTable)   
    {  
        //Create Empty Table  
        DataTable ResultDataTable = new DataTable("ResultDataTable");  
    
        //use a Dataset to make use of a DataRelation object  
        using (DataSet ds = new DataSet())  
        {      
            //Add tables      
            ds.Tables.AddRange(new DataTable[] { FirstDataTable.Copy(), SecondDataTable.Copy()  });
    
            //Get Columns for DataRelation  
            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];  
            }  
    
            //Create DataRelation  
            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);  
    
            //Create columns for return table  
            for (int i = 0; i < FirstDataTable.Columns.Count; i++)  
            {  
                ResultDataTable.Columns.Add(FirstDataTable.Columns[i].ColumnName, FirstDataTable.Columns[i].DataType);  
            }  
    
            //If FirstDataTable Row not in SecondDataTable, Add to ResultDataTable.  
            ResultDataTable.BeginLoadData();  
            foreach (DataRow parentrow in ds.Tables[0].Rows)  
            {  
                DataRow[] childrows = parentrow.GetChildRows(r1);  
                if (childrows == null || childrows.Length == 0)  
                    ResultDataTable.LoadDataRow(parentrow.ItemArray, true);  
            }  
    
            //If SecondDataTable Row not in FirstDataTable, Add to ResultDataTable.  
            foreach (DataRow parentrow in ds.Tables[1].Rows)  
            {  
              DataRow[] childrows = parentrow.GetChildRows(r2);  
              if (childrows == null || childrows.Length == 0)  
                ResultDataTable.LoadDataRow(parentrow.ItemArray, true);  
            }  
            ResultDataTable.EndLoadData();  
        }
    
        return ResultDataTable;   
    }
    

    【讨论】:

      【解决方案3】:

      您需要遍历每个表的行,然后遍历该循环中的每一列来比较各个值。

      这里有一个代码示例:compare two datatables

      简而言之,方法应该是这样的:

      bool compareTbls(Datatable OldDataTable, Datatable NewDataTable)
      {
          if(OldDataTable.Rows.Count != NewDataTable.Rows.Count || OldDataTable.Columns.Count != NewDataTable.Columns.Count)
              return false;
      
          for(int i = 0; i < OldDataTable.Rows.Count; i++)
          {
              for(int c = 0; c < OldDataTable.Columns.Count; c++)
              {
                  if(OldDataTable.Rows[i][c] != NewDataTable.Rows.Columns[i][c])
                      return false;
              }
          }
      
          return true;
      }
      

      【讨论】:

        【解决方案4】:

        使用 linq 和 2 连接,很容易获得更改(添加、删除或更新)行的确切集合。这是一个完整的例子:

            class Data {
                public int ID;
                public int value;
            }
        
            enum RowState {
                Added,
                Updated,
                Deleted
            }
        
            List<Data> OldDataTable = new List<Data> { 
                    new Data { ID = 1, value = 0 }, 
                    new Data { ID = 2, value = 0 }, 
                    new Data { ID = 3, value = 1 } 
            };
            List<Data> NewDataTable = new List<Data> { 
                    new Data { ID = 1, value = 0 },
                    new Data { ID = 2, value = 1 },
                    new Data { ID = 4, value = 2 } 
            }; 
        
            void Test() {
                //updated and deleted rows
                var udRows = 
                    from Old in OldDataTable
                    join n in NewDataTable on Old.ID equals n.ID 
                    into NewWithNullForDeleted
                    from subNew in NewWithNullForDeleted.DefaultIfEmpty()
                    where subNew == null || Old.value != subNew.value
                    select new {
                        ID = Old.ID,
                        OldValue = (int?)Old.value,
                        NewValue = subNew == null ? (int?)null : (int?)subNew.value,
                        RowState = subNew == null ? RowState.Deleted : RowState.Updated
                    };
                //added rows
                var aRows = 
                    from New in NewDataTable
                    join o in OldDataTable on New.ID equals o.ID 
                    into OldWithNullForAdded
                    from subOld in OldWithNullForAdded.DefaultIfEmpty()
                    where subOld == null
                    select new {
                        ID = New.ID,
                        OldValue = (int?)null,
                        NewValue = (int?)New.value,
                        RowState = RowState.Added
                    };
                //merge
                var changedRows = udRows.ToList();
                changedRows.AddRange(aRows);
        
                //display
                foreach (var changedRow in changedRows) {
                    Console.WriteLine("{0} : '{1}' -> '{2}' ({3})",
                    changedRow.ID, 
                    changedRow.OldValue, changedRow.NewValue,
                    changedRow.RowState);
                }
            }
        

        使用此示例数据运行Test 方法将输出以下内容:

        2 : '0' -> '1' (Updated)
        3 : '1' -> '' (Deleted)
        4 : '' -> '2' (Added)
        

        希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 2011-11-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-14
          • 1970-01-01
          • 2020-02-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多