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

如何仅用LINQ将Excel生成的DataTable更新至SQL表tblExportOrderdatas?

问题分析与修正方案

咱们先拆解下你当前代码里的核心问题,这也是数据没保存成功的原因:

  1. 方向完全错了:你循环里新建tblExportOrderdata对象然后调用AddObject,这是在往数据库新增数据,而不是更新你已经查询到的objtblInbox里的现有记录。EF的AddObject是用来添加新实体的,修改现有实体根本不需要这个方法。
  2. 循环逻辑混乱:外层遍历要更新的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:18:28