如何在c#中有效地比较两个数据表

本文关键字:两个 数据表 比较 有效地 | 更新日期: 2023-09-27 18:06:27

我正在研究一个方法,该方法接受两个数据表和一个主键列名列表,并返回匹配项。我没有其他关于桌子的信息。

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

基于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);    

如何在c#中有效地比较两个数据表

使用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();

在一个包含2个表9900行并返回9800行的测试中,这花费了大约1/3秒。