【问题标题】:Compare two DataTable Multi fields比较两个 DataTable 多字段
【发布时间】:2011-10-30 13:29:05
【问题描述】:
        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" });

result 应该只包含 dt1 中不存在的值。我们可以用 linq 做到这一点吗

【问题讨论】:

  • 一定要用DataTables入手吗?

标签: .net ado.net dataset


【解决方案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 方法是 根据EqualsGetHashcode 的方法定义 属性,相同匿名类型的两个实例仅当 它们的所有属性都是相等的。

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

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

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

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

var dt2NotInDt1 = 
    for r2 in dataRows2
    let r1Exists = dataRows1Map.ContainsKey(r2.Id)
    let r1 = r1Exists ? dataRows1Map[r2.Id] : null
    where 
        // Rows that don't have a primary key in the first set.
        !r1Exists ||
        // Rows that are different.
        !r1.Equals(r2)
    select r2;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-03
    • 2023-03-05
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多