如何仅用LINQ将Excel生成的DataTable更新至SQL表tblExportOrderdatas?
问题分析与修正方案
咱们先拆解下你当前代码里的核心问题,这也是数据没保存成功的原因:
- 方向完全错了:你循环里新建
tblExportOrderdata对象然后调用AddObject,这是在往数据库新增数据,而不是更新你已经查询到的objtblInbox里的现有记录。EF的AddObject是用来添加新实体的,修改现有实体根本不需要这个方法。 - 循环逻辑混乱:外层遍历要更新的SQL实体,内层遍历整个DataTable的所有行,这会导致每个SQL实体被反复赋值(最后一次遍历的DataRow会覆盖之前的),而且最关键的是——你没有任何匹配逻辑,怎么确定DataTable里的哪一行对应SQL里的哪一条记录?没有关联条件的更新完全是瞎操作。
正确实现思路(基于LINQ+EF)
要实现需求,核心是用LINQ关联SQL中的目标记录和Excel里的更新数据,然后直接修改EF上下文跟踪的实体,最后保存更改即可。
步骤1:先把DataTable转成强类型集合(可选但推荐)
直接操作DataRow不够优雅,转成强类型后LINQ操作更顺畅:
// 定义一个类对应Excel里的更新数据,根据实际字段调整 public class ExcelUpdateInfo { // 必须要有一个和SQL表匹配的唯一标识字段,比如Batch_ID或者主键ID public int Batch_ID { get; set; } public string Updated_Supplier_Remark { get; set; } public DateTime Updated_Date { get; set; } } // 把DataTable转换成强类型集合 var excelUpdateList = copydt.AsEnumerable() .Select(dr => new ExcelUpdateInfo { Batch_ID = Convert.ToInt32(dr["Batch_ID"]), // 这里要和Excel里的对应字段名一致 Updated_Supplier_Remark = dr["Updated_Supplier_Remarks"].ToString(), Updated_Date = Convert.ToDateTime(dr["Updated_Date"]) }) .ToList();
步骤2:关联SQL记录与Excel数据并更新
int sid = Convert.ToInt32(sExportID); // 从EF上下文获取要更新的SQL记录,ToList()后在内存中操作 var targetSqlRecords = objLCSEntities.tblExportOrderdatas .Where(m => m.Batch_ID == sid) .ToList(); // 用LINQ Join关联SQL记录和Excel更新数据,匹配条件根据实际业务调整 var matchedRecords = from sqlRec in targetSqlRecords join excelRec in excelUpdateList on sqlRec.Batch_ID equals excelRec.Batch_ID // 如果是每行对应不同的SQL记录,这里应该用主键ID匹配,比如sqlRec.ID == excelRec.ID select new { SqlRecord = sqlRec, ExcelData = excelRec }; // 遍历匹配结果,更新对应字段 foreach (var pair in matchedRecords) { // 只在Excel数据不为空时更新Supplier_Remark if (!string.IsNullOrEmpty(pair.ExcelData.Updated_Supplier_Remark)) { pair.SqlRecord.Supplier_Remark = pair.ExcelData.Updated_Supplier_Remark; } // 更新Date字段,根据需求可以加判断(比如是否允许覆盖空值) pair.SqlRecord.Date = pair.ExcelData.Updated_Date; } // 提交更改到数据库 objLCSEntities.SaveChanges();
特殊情况:同批次所有记录更新为相同值
如果你的Excel里只有一行对应这个批次(Batch_ID=sid)的更新数据,不需要逐行匹配,可以简化代码:
int sid = Convert.ToInt32(sExportID); var targetSqlRecords = objLCSEntities.tblExportOrderdatas .Where(m => m.Batch_ID == sid) .ToList(); // 获取Excel中对应批次的更新数据 var excelUpdate = copydt.AsEnumerable() .FirstOrDefault(dr => Convert.ToInt32(dr["Batch_ID"]) == sid); if (excelUpdate != null) { foreach (var rec in targetSqlRecords) { if (!string.IsNullOrEmpty(excelUpdate["Updated_Supplier_Remarks"].ToString())) { rec.Supplier_Remark = excelUpdate["Updated_Supplier_Remarks"].ToString(); } rec.Date = Convert.ToDateTime(excelUpdate["Updated_Date"]); } } objLCSEntities.SaveChanges();
关键要点总结
- EF中修改现有实体不需要调用AddObject,只要修改从上下文获取的实体对象,EF会自动跟踪变化,
SaveChanges()时会自动生成更新语句。 - 必须有明确的关联匹配条件(比如主键、Batch_ID),否则无法准确对应SQL记录和Excel数据。
- 转换成强类型集合能让LINQ操作更清晰,减少直接操作DataRow的出错概率。
内容的提问来源于stack exchange,提问作者niketa
相关产品推荐
相关产品推荐

