【问题标题】:Compare two DataTables with several keys and select the rows that are not present in second table比较两个具有多个键的 DataTables 并选择第二个表中不存在的行
【发布时间】:2018-08-20 04:41:33
【问题描述】:

我有两个数据表,我想从第一个中选择第二个中不存在的行,两个表都有 3 个键 custnum、shiptonum、connum

例如:

表联系人

custnum  shiptonum  connum  column
   1        1         1     data1    
   2        2         2     data2
   3        3         3     data3
   4        4         4     data4

餐桌邀请

custnum  shiptonum  connum  column
   1        1         1     data11
   3        3         3     data33

我希望结果是:

表格结果

custnum  shiptonum  connum  column
   2        2         2     data2
   4        4         4     data4 

我已经尝试过使用

var 差异 = table1.AsEnumerable().Except(table2.AsEnumerable(),DataRowComparer.Default);

但它没有用。例如,在我在 Contacts 表中的测试中,我有 14,389 条记录,在 Invitations 表中我有两条记录存在于 Contacts 表中,使用上述解决方案后的计数是 14,389 而不是 14,387(从 Invitations 表中删除这两条记录)。

【问题讨论】:

  • 可能你需要这样的东西:var differences = table1.AsEnumerable().Except(table2.AsEnumerable(),DataRowComparer.Default);.
  • 它不起作用@TetsuyaYamamoto,例如在我在联系人表中的测试中我有 14,389 条记录,在表邀请中我有两条记录存在于联系人表中,使用建议的解决方案后的计数是 14,389而不是 14,387(从邀请表中删除两条记录)。

标签: c# linq datatable


【解决方案1】:

你写道:

我想从第一个中选择第二个中不存在的行

从您的示例中,我看到您不想从第一个表中选择不是第二个表中的行的行,而是只想考虑键的值:

我想从 tableA 中选择所有行,其中键的值不是来自 tableB 的键

您没有定义您的表格。它们可能是 IQueryableIEnumerable,对于您的 LINQ 语句来说,差别不大。尽量避免AsEnumerable,特别是如果您的数据源位于不同的进程中,例如数据库管理系统。另一个进程在执行查询方面比您的进程更有效。 AsEnumerable 将所有数据从您的其他进程传输到您的进程,这是一个相对较慢的过程。因此,原则上:仅在确实需要时才使用AsEnumerable

第二个定义更清楚地定义了你想要什么:显然从tableB 你只需要键:

var keysTableB = tableB.Select(row => new
    {
         CustNum = row.custNum,
         ShipToNum = row.shiptonum,
         ConNum = row.connum,
    });

换句话说:从 tableB 中的每一行创建一个具有三个属性的匿名类型新对象:CustNumShipToNumConNum

Select 使用延迟执行。不执行任何查询,仅更改属性Expression

现在您只想保留来自tableA 的行,其键是序列keysTableB 的成员:如果您想保留序列的子集,请使用Where

var result = tableA.Where(row => keysTableB.Contains(new
    {
         CustNum = row.custNum,
         ShipToNum = row.shiptonum,
         Connum = row.connum,
    }));

换句话说:从 tableB 的每一行中,使用值相等,只保留那些键也在 keysTableB 中的行。

TODO:考虑将这两个 LINQ 语句合并为一个。
我怀疑这是否会提高性能。它肯定会降低代码的可读性,从而降低可更改性/维护性/可测试性。

【讨论】:

    【解决方案2】:
    for (int i=0;i<table1.rows.count;i++)
    {
       var rowExists = from dr in table2.AsEnumerable()
                       where dr.Field<typeofcolumn>("colum_name")==table1.Rows[i]["column_name"]
                       select dr;
      if(rowExists.ToList().Count==0)
      {
          //here u import row table1.rows[i] to new table
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-05
      • 1970-01-01
      • 2019-09-12
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多