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

C#中如何高效合并主键不同的一对多DataTable?

高效实现DataTable内连接(INNER JOIN)的方案

针对10k-15k行的DataTable,LINQ循环赋值效率低的问题,推荐以下两种高效方案:

方案一:哈希表缓存+遍历匹配(最优性能)

利用哈希表O(1)的查找特性,先缓存dt1的主键映射,再遍历dt2快速匹配,整体时间复杂度为O(M+N),适合大数据量场景。

// 1. 构建dt1的哈希缓存,Key为Code值,Value为对应DataRow
var dt1Cache = new Dictionary<object, DataRow>();
foreach (DataRow row in dt1.Rows)
{
    object codeKey = row["Code"];
    if (!dt1Cache.ContainsKey(codeKey))
    {
        dt1Cache.Add(codeKey, row);
    }
}

// 2. 创建结果DataTable,合并dt1与dt2的列结构(处理列名冲突)
DataTable resultDt = dt1.Clone();
foreach (DataColumn col in dt2.Columns)
{
    string targetColName = col.ColumnName;
    // 若列名重复,给dt2的列加前缀区分
    if (resultDt.Columns.Contains(targetColName))
    {
        targetColName = $"dt2_{targetColName}";
    }
    resultDt.Columns.Add(targetColName, col.DataType);
}

// 3. 遍历dt2,匹配dt1数据并插入结果表
foreach (DataRow dt2Row in dt2.Rows)
{
    object fCode = dt2Row["F_Code"];
    if (dt1Cache.TryGetValue(fCode, out DataRow dt1Row))
    {
        DataRow newRow = resultDt.NewRow();
        // 复制dt1的列数据
        foreach (DataColumn col in dt1.Columns)
        {
            newRow[col.ColumnName] = dt1Row[col.ColumnName];
        }
        // 复制dt2的列数据
        foreach (DataColumn col in dt2.Columns)
        {
            string targetColName = resultDt.Columns.Contains(col.ColumnName) ? $"dt2_{col.ColumnName}" : col.ColumnName;
            newRow[targetColName] = dt2Row[col.ColumnName];
        }
        resultDt.Rows.Add(newRow);
    }
}

方案二:DataSet+DataRelation(代码更规整)

借助ADO.NET内置的DataRelation关联两张表,通过父/子行获取匹配数据,性能略逊于哈希表方案,但代码更简洁易维护。

// 1. 将两张表加入DataSet
DataSet ds = new DataSet();
ds.Tables.Add(dt1.Copy());
ds.Tables.Add(dt2.Copy());

// 2. 定义关联关系:dt1.Code <-> dt2.F_Code
DataRelation joinRelation = new DataRelation(
    "Dt1_Dt2_Join",
    ds.Tables[0].Columns["Code"],
    ds.Tables[1].Columns["F_Code"]);
ds.Relations.Add(joinRelation);

// 3. 创建结果表结构(同方案一,处理列名冲突)
DataTable resultDt = dt1.Clone();
foreach (DataColumn col in dt2.Columns)
{
    string targetColName = col.ColumnName;
    if (resultDt.Columns.Contains(targetColName))
    {
        targetColName = $"dt2_{targetColName}";
    }
    resultDt.Columns.Add(targetColName, col.DataType);
}

// 4. 遍历dt2,通过关联关系获取匹配的dt1行并合并
foreach (DataRow dt2Row in ds.Tables[1].Rows)
{
    DataRow[] matchedDt1Rows = dt2Row.GetParentRows(joinRelation);
    if (matchedDt1Rows.Length > 0)
    {
        DataRow dt1Row = matchedDt1Rows[0];
        DataRow newRow = resultDt.NewRow();
        // 复制dt1数据
        foreach (DataColumn col in dt1.Columns)
        {
            newRow[col.ColumnName] = dt1Row[col.ColumnName];
        }
        // 复制dt2数据
        foreach (DataColumn col in dt2.Columns)
        {
            string targetColName = resultDt.Columns.Contains(col.ColumnName) ? $"dt2_{col.ColumnName}" : col.ColumnName;
            newRow[targetColName] = dt2Row[col.ColumnName];
        }
        resultDt.Rows.Add(newRow);
    }
}

注意事项

  • 确保dt1的Code与dt2的F_Code数据类型完全一致,否则匹配会失败。
  • 列名冲突必须处理,否则创建结果表时会抛出异常,示例中通过添加dt2_前缀解决。
  • dt1的Code作为主键,确保无重复值,避免哈希缓存出现覆盖问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 02:44:52