【问题标题】:compare datatables and save unmatched rows in third datatable比较数据表并将不匹配的行保存在第三个数据表中
【发布时间】:2015-08-04 19:52:03
【问题描述】:

我正在尝试比较两个数据表并捕获第三个数据表中的差异。

DataTable one = new DataTable();
one.Columns.Add("ID");
one.Columns.Add("PCT");
one.Rows.Add("1", "0.1");
one.Rows.Add("2", "0.2");
one.Rows.Add("3", "0.3");
DataTable two = new DataTable();
two.Columns.Add("ID");
two.Columns.Add("PCT");
two.Columns.Add("OldPCT");
two.Rows.Add("1", "0.1", "0");
two.Rows.Add("2", "0.1", "0");
two.Rows.Add("3", "0.9", "0");
two.Columns.Remove("OldPCT");

//First method
DataTable three = two.AsEnumerable().Except(one.AsEnumerable()).CopyToDataTable();
foreach (DataRow dr in three.AsEnumerable())
{
    string strID = dr[0].ToString();
    string strPCT = dr[1].ToString();
}

//second method
var diffName = two.AsEnumerable().Select(r => r.Field<string>("PCT")).Except(one.AsEnumerable().Select(r => r.Field<string>("PCT")));
if (diffName.Any())
{
    DataTable Table3 = (from row in two.AsEnumerable()
                        join name in diffName
                        on row.Field<string>("PCT") equals name
                        select row).CopyToDataTable();
}

到目前为止,我已经尝试了两种方法,但没有得到预期的结果,应该是这样的。

在第三个数据表中,值应如下所述。

 ID    PCT
 2     O.1
 3     0.9   

最近的一个:

DataTable one = new DataTable();
one.Columns.Add("ID");
one.Columns.Add("PCT");
one.Rows.Add("1", "0.1");
one.Rows.Add("2", "0.2");
one.Rows.Add("2", "0.2");
one.Rows.Add("3", "0.3");
one.Rows.Add("3", "0.3");
DataTable two = new DataTable();
two.Columns.Add("ID");
two.Columns.Add("PCT");
two.Rows.Add("1", "0.1");
two.Rows.Add("2", "0.1");
two.Rows.Add("2", "0.1");
two.Rows.Add("3", "0.8");
two.Rows.Add("3", "0.9");

现在我需要从数据表 2 中获取除第一行之外的所有行。但我只得到最后三行。

【问题讨论】:

  • 请记住,DataTable 有一个 GetChanges() method。只需合并表格,然后调用GetChanges(),它会返回第三个DataTable

标签: c# asp.net linq datatable


【解决方案1】:

你需要一个自定义的 IEqualityComparer

void Main()
{
   DataTable one = new DataTable();
   one.Columns.Add("ID");
   one.Columns.Add("PCT");
   one.Rows.Add("1", "0.1");
   one.Rows.Add("2", "0.2");
   one.Rows.Add("3", "0.3");
   DataTable two = new DataTable();
   two.Columns.Add("ID");
   two.Columns.Add("PCT");
   two.Columns.Add("OldPCT");
   two.Rows.Add("1", "0.1", "0");
   two.Rows.Add("2", "0.1", "0");
   two.Rows.Add("3", "0.9", "0");
   two.Columns.Remove("OldP

   DataTable three = two.AsEnumerable().Except(one.AsEnumerable(),new RowEqualityComparer()).CopyToDataTable();
   foreach (DataRow dr in three.AsEnumerable())
   {
       string strID = dr[0].ToString();
       string strPCT = dr[1].ToString();
   }
}


class RowEqualityComparer : IEqualityComparer<DataRow>
{
   public bool Equals(DataRow b1, DataRow b2)
   {
     if ((b1.Field<string>("ID") == b2.Field<string>("ID")) && (b1.Field<string>("PCT") == b2.Field<string>("PCT")))
     {
       return true;
     }
     else
     {
       return false;
     }
   }

   public int GetHashCode(DataRow bx)
   {
     return (bx.Field<string>("ID")+bx.Field<string>("PCT")).GetHashCode();
   }
}

【讨论】:

  • 如果结果为 0 表示如果没有变化,我会收到此错误源包含没有 DataRows.. 我该如何处理?
  • 添加一个我猜的 if 语句
【解决方案2】:

基于 Hogan 的回答,您可以使用 DataRowComparer.Default 作为 Except() 方法的第二个参数(而不是创建自定义 IEqualityComparer):

// this will get all rows from table two that don't match rows in one
// the result is an IEnumerable<DataRow> 
var unmatched = two.AsEnumerable()
  .Except(one.AsEnumerable(), DataRowComparer.Default);

// CopyToDataTable converts an IEnumerable<DataRow> into a DataTable
// but it blows up if the source object is empty

// this statement makes sure unmatched has data before calling CopyToDataTable()
// if it is empty, we 'clone' (make an empty copy) of one of the original DataTables
var three = unmatched.Any() ? unmatched.CopyToDataTable() : one.Clone();

这将对每行中的字段进行基于值的比较,以确定它们是否相等。

【讨论】:

  • 如果结果为 0 表示如果没有变化,我收到此错误 The source contains no DataRows.。我该如何处理?
  • 这可能来自 CopyToDataTable() 方法。查看这篇文章了解如何处理它:stackoverflow.com/questions/7815916/…
  • 我对 .net 很陌生,我还不足以理解这一点,所以请你帮我解决这个问题。很抱歉打扰您。
  • 当然,我已经用代码更新了我的示例,以处理没有更改的情况。我还添加了一堆 cmets 来解释发生了什么。
  • 我认为默认行不通,因为他只想检查两个字段
猜你喜欢
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-06
  • 2017-09-30
  • 1970-01-01
  • 2021-06-17
相关资源
最近更新 更多