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

Linq操作未知列DataTable 多库关联合并新增年份列问题

解决方案

方案1:直接操作DataTable完成合并(推荐,性能最高、代码最简洁)

完全不需要用LINQ Join加转换的复杂逻辑,直接给总表新增列后匹配赋值即可:

da.Fill(tempDT);
string newColName = "GOD" + godina.ToString();
// 1. 给总表添加对应年份的新列
dt.Columns.Add(newColName, typeof(decimal));

// 2. 给临时表设置联合主键,大幅提升匹配速度
tempDT.PrimaryKey = new DataColumn[] 
{ 
    tempDT.Columns["MAGACINID"], 
    tempDT.Columns["ROBAID"] 
};

// 3. 遍历总表匹配赋值
foreach (DataRow row in dt.Rows)
{
    var matchedRow = tempDT.Rows.Find(new object[] 
    { 
        row["MAGACINID"], 
        row["ROBAID"] 
    });
    row[newColName] = matchedRow != null ? matchedRow[newColName] : DBNull.Value;
    // 没有匹配数据时也可填0:row[newColName] = matchedRow != null ? matchedRow[newColName] : 0;
}

不需要再调用LINQResultToDataTable方法,这段代码直接完成合并逻辑。

方案2:修改LINQ投影逻辑

如果一定要用LINQ实现,可以在Join的投影阶段直接展开原有行的所有列,避免嵌套DataRow对象:

// 提前获取总表已有列名
var existColumns = dt.Columns.Cast<DataColumn>().Select(c => c.ColumnName).ToList();
string newColName = "GOD" + godina.ToString();

var result = dt.AsEnumerable()
    .Join(tempDT.AsEnumerable(),
        x => new { Magacin = x["MAGACINID"], Roba = x["ROBAID"] },
        y => new { Magacin = y["MAGACINID"], Roba = y["ROBAID"] },
        (x, y) => 
        {
            IDictionary<string, object> res = new ExpandoObject();
            // 展开原有行的所有列
            foreach (var col in existColumns)
            {
                res[col] = x[col];
            }
            // 添加新年份列
            res[newColName] = y[newColName];
            return res;
        });

dt = LINQResultToDataTable(result);

方案3:修改通用转换方法适配嵌套DataRow

如果你不想修改业务逻辑,仅修改通用转换方法即可实现自动拆分DataRow属性:

private DataTable LINQResultToDataTable<T>(IEnumerable<T> Linqlist)
{
    DataTable dt = new DataTable();
    // 存储DataRow类型属性对应的列映射
    Dictionary<string, List<DataColumn>> rowPropMapping = new Dictionary<string, List<DataColumn>>();

    if (Linqlist == null || !Linqlist.Any()) return dt;

    foreach (T Record in Linqlist)
    {
        if (dt.Columns.Count == 0)
        {
            var allProps = Record.GetType().GetProperties();
            foreach (var prop in allProps)
            {
                // 识别DataRow类型的属性,拆分其所有列
                if (typeof(DataRow).IsAssignableFrom(prop.PropertyType))
                {
                    var sampleRow = prop.GetValue(Record) as DataRow;
                    var subCols = sampleRow.Table.Columns.Cast<DataColumn>().ToList();
                    rowPropMapping[prop.Name] = subCols;
                    foreach (var col in subCols)
                    {
                        if (!dt.Columns.Contains(col.ColumnName))
                        {
                            dt.Columns.Add(col.ColumnName, col.DataType);
                        }
                    }
                }
                else
                {
                    Type colType = prop.PropertyType;
                    if (colType.IsGenericType && colType.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        colType = colType.GetGenericArguments()[0];
                    }
                    dt.Columns.Add(prop.Name, colType);
                }
            }
        }

        DataRow dr = dt.NewRow();
        var props = Record.GetType().GetProperties();
        foreach (var prop in props)
        {
            var val = prop.GetValue(Record, null);
            if (val is DataRow rowVal)
            {
                // 拆分赋值DataRow的所有子列
                foreach (var col in rowPropMapping[prop.Name])
                {
                    dr[col.ColumnName] = rowVal[col] ?? DBNull.Value;
                }
            }
            else
            {
                dr[prop.Name] = val ?? DBNull.Value;
            }
        }
        dt.Rows.Add(dr);
    }
    return dt;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 16:57:02