You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#高效对比两个DataTable,获取新增/更新/删除行

高效对比大DataTable(新增/更新/删除行)的LINQ实现方案

针对两个10万+行的DataTable(今日/昨日表,均含唯一列Master_ID),直接逐行全量遍历性能极差。以下是基于LINQ+字典映射的高效实现方案,核心思路是通过Master_ID构建哈希字典,将查找操作的时间复杂度从O(n)降至O(1):

实现步骤

  1. 为两张表分别构建Master_ID到DataRow的字典映射,避免重复遍历查找
  2. 筛选新增行:今日表中Master_ID不存在于昨日表的行
  3. 筛选删除行:昨日表中Master_ID不存在于今日表的行
  4. 筛选更新行:Master_ID同时存在于两张表,但行内容存在差异的行

代码实现

首先定义行内容对比方法(DataRow默认Equals为引用比较,需自定义值对比逻辑):

private static bool AreRowsEqual(DataRow row1, DataRow row2)
{
    foreach (DataColumn col in row1.Table.Columns)
    {
        // 处理DBNull.Value的空值情况
        var val1 = row1[col] == DBNull.Value ? null : row1[col];
        var val2 = row2[col] == DBNull.Value ? null : row2[col];
        if (!Equals(val1, val2))
        {
            return false;
        }
    }
    return true;
}

主对比逻辑:

public Dictionary<string, List<DataRow>> CompareLargeDataTables(DataTable todayTable, DataTable yesterdayTable)
{
    // 构建昨日表的ID-行映射,一次遍历完成
    var yesterdayRowMap = yesterdayTable.AsEnumerable()
        .ToDictionary(row => row["Master_ID"].ToString(), row => row);
    
    // 构建今日表的ID-行映射
    var todayRowMap = todayTable.AsEnumerable()
        .ToDictionary(row => row["Master_ID"].ToString(), row => row);
    
    // 新增行:今日有,昨日无
    var added = todayTable.AsEnumerable()
        .Where(row => !yesterdayRowMap.ContainsKey(row["Master_ID"].ToString()))
        .ToList();
    
    // 删除行:昨日有,今日无
    var deleted = yesterdayTable.AsEnumerable()
        .Where(row => !todayRowMap.ContainsKey(row["Master_ID"].ToString()))
        .ToList();
    
    // 更新行:ID存在,但内容不同
    var updated = todayTable.AsEnumerable()
        .Where(row => 
        {
            var id = row["Master_ID"].ToString();
            return yesterdayRowMap.TryGetValue(id, out var yesterdayRow) && !AreRowsEqual(row, yesterdayRow);
        })
        .ToList();
    
    return new Dictionary<string, List<DataRow>>
    {
        ["Added"] = added,
        ["Updated"] = updated,
        ["Deleted"] = deleted
    };
}

性能优化提示

  • 强类型键优化:如果Master_ID是int/long等值类型,直接用原类型作为字典键,避免字符串转换的性能开销
  • 列范围缩小:如果不需要对比所有30列,可修改AreRowsEqual方法只对比指定列,减少计算量
  • 哈希预计算:对行内容预计算哈希值(如将列值组合成Tuple或拼接成唯一字符串后取HashCode),可进一步加快行对比速度,但需注意处理空值和类型冲突问题

内容的提问来源于stack exchange,提问作者Aashish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 04:10:35