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
相关产品推荐
相关产品推荐

