【问题标题】:How to efficiently compare two data tables in C#如何在 C# 中有效地比较两个数据表
【发布时间】:2014-07-24 11:54:12
【问题描述】:

我正在研究一种方法,该方法接收两个数据表和一个主键列名称列表并返回匹配项。我没有关于这些表的任何其他信息。

我已经在该网站上搜索了该问题的解决方案并找到了一些答案,但没有一个给我足够快的解决方案。

根据 stackoverflow 的结果,我现在有了这个:

var matches =
    (from rowA in tableA.AsEnumerable()
     from rowB in tableB.AsEnumerable()
     where primaryKeyColumnNames.All(column => rowA[column].ToString() == rowB[column].ToString())
     select new { rowA, rowB });

问题是这真的很慢。两张 8000 行的表需要 4 分钟。在我开始使用 stackoverflow 之前,我实际上是在遍历列和行,这需要 2 分钟。 (所以这实际上比我所拥有的要慢) 2-4 分钟似乎并没有那么糟糕,直到我用 350,000 行打到桌子上。这需要几天时间。我需要找到更好的解决方案。

谁能想到一个更快的方法?

编辑:根据 tinstaafl 的建议,现在这是我的代码。

var matches = tableA.Rows.Cast<DataRow>().Select(rowA => new 
{
    rowA,
    rowB = tableB.Rows.Find(rowA.ItemArray.Where((x, y) => 
        primaryKeyColumnNames.Contains(tableA.Columns[y].ColumnName,
               StringComparer.InvariantCultureIgnoreCase)).ToArray())
})
.Where(x => x.rowB != null);    

【问题讨论】:

  • 等效的手工 SQL 查询的时间是多少?那是它可以走的最快速度。听起来整个过程都很缓慢。
  • 我必须研究跨数据库查询。

标签: c# linq datatable


【解决方案1】:

使用将接受列数组的DataTablePrimaryKey 属性应该会有所帮助。也许是这样的:

tableA.PrimaryKey = primaryKeyColumnNames.Select(x => tableA.Columns[x]).ToArray();
tableB.PrimaryKey = primaryKeyColumnNames.Select(x => tableB.Columns[x]).ToArray();
var matches = (from System.Data.DataRow RowA in tableA.Rows
                where tableB.Rows.Contains(RowA.ItemArray.Where((x,y) => primaryKeyColumnNames.Contains(tableA.Columns[y].ColumnName)).ToArray())
                select RowA).ToList();

在一个包含 9900 行的 2 个表的测试中,通常返回 9800,这大约需要 1/3 秒。

【讨论】:

  • 谢谢!我现在就试试这个。我正在陷入困境,即将尝试对 pks 进行哈希处理,或者在 F# 中重写应用程序
  • 我修改了你的解决方案,我即将开始测试。您可以在上面看到我的更改。如果可行,我会选择你的答案!
  • 我提交的代码不管列的顺序如何都可以工作,因为它依赖于列名。
  • @tinstaafl... lambda 中的“y”是列索引,而不是名称。当我更改第二个表中列的顺序时,代码失败了。我用它来修复:stackoverflow.com/questions/3757997/…
  • y 仅用于从 itemarray 索引中获取列名。列顺序必须与该数据表的数据行中的 itemarray 的顺序相匹配。比较是通过列名完成的。如果两个表之间的列顺序不匹配,代码可能需要调整。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
相关资源
最近更新 更多