比较两个DataTable Multi字段

时间:2011-08-19 11:36:29

标签: .net ado.net dataset

        DataTable dt1 = new DataTable();
        DataTable dt2 = new DataTable();

        dt1.Columns.Add("id");
        dt2.Columns.Add("id");

        dt1.Columns.Add("val1");
        dt2.Columns.Add("val1");

        dt1.Columns.Add("val2");
        dt1.Columns.Add("val2");


        dt1.Rows.Add(new string[] { "1", "a", "a1" });
        dt1.Rows.Add(new string[] { "2", "b", "b1" });
        dt1.Rows.Add(new string[] { "", "b", "b1" });
        dt1.Rows.Add(new string[] { "4", "", "c1" });


        dt2.Rows.Add(new string[] { "1", "a", "a1" });
        dt2.Rows.Add(new string[] { "2", "b", "b1" });
        dt2.Rows.Add(new string[] { "3", "c", "c1" });
        dt2.Rows.Add(new string[] { "3", "c", "c1" });
        dt2.Rows.Add(new string[] { "4", "d", "d1" });
        dt2.Rows.Add(new string[] { "5", "e", "e1" });

结果应仅包含dt1中不存在的值。我们可以用linq

来做到这一点

1 个答案:

答案 0 :(得分:1)

是的,您可以使用LINQ执行此操作,我会这样做:

var dataRows1 = st1.AsEnumerable().Select(r => new { 
    Id = r["id"], Val1 = r["val1"], Val2 = r["val2"] });

var dataRows2 = st2.AsEnumerable().Select(r => new { 
    Id = r["id"], Val1 = r["val1"], Val2 = r["val2"] });

这为您提供了IEnumerable<T>个可以与之比较的匿名类型。然后,你可以这样做:

var dt2NotInDt1 = dataRows2.Where(r2 => !dataRows1.Any(r1 => r1.Equals(r2));

请注意,这假设您的比较条件是行中的所有值(包括id)。

另请注意拨打Equals的电话。匿名类型覆盖Equals方法,以提供匿名类型的所有属性的值比较。来自"Anonymous Types" section of the C# Programming Guide

  

因为匿名类型上的EqualsGetHashCode方法是   根据{{​​1}}和Equals方法定义   属性,同一匿名类型的两个实例仅在相等时才相等   他们所有的财产都是平等的。

您可以根据约束条件简化此逻辑。例如,如果存在主键(或某种唯一行标识符),则可以将行放在键入该值的字典中,然后根据该值执行查找。

在您的情况下,假设GetHashcode是唯一的,您可以这样做(在顶部的前两行之后):

id

这将为您提供一个地图,然后您可以对其进行查找(我正在切换到查询语法,因为我相信它在这里更具可读性。)

var dataRows1Map = dataRows1.ToDictionary(r => r.Id);