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

.NET Core中如何更新List<T>对象元素而非新增行

问题解决方法

核心问题分析

  1. 视图未提交主键值:你用@Html.DisplayFor展示DefectId,但这个助手只会生成纯文本,不会生成带name属性的表单控件,导致提交到控制器时,每个Defect对象的DefectId都是默认值(比如0)。EF Core会把主键为默认值的实体判定为新实体,执行新增操作。
  2. 控制器逻辑错误:不管实体是已存在还是新创建的,你都调用db.Defects.Add(i),这个方法始终会把实体标记为待新增状态。

第一步:修改视图,确保主键被提交

在展示DefectId的<td>里添加隐藏字段,让表单提交时带上主键值:

<td>
    @Html.DisplayFor(a => a[i].DefectId)
    @Html.HiddenFor(a => a[i].DefectId) <!-- 新增这行,提交主键值 -->
</td>

如果JobId、DefectCreatedDate、DefectCreatedBy这些字段需要完整回传(即使不可修改),也可以给它们添加对应的隐藏字段,保证模型绑定的完整性。


第二步:修改控制器逻辑,区分新增与更新

方案一:查询现有实体后更新(推荐,更安全)

先从数据库获取对应实体,再修改需要更新的属性,EF会自动跟踪变化:

[HttpPost]
public IActionResult Defectlist(List<Defect> model)
{
    if (ModelState.IsValid)
    {
        foreach(var item in model)
        {
            var existingDefect = db.Defects.FirstOrDefault(d => d.DefectId == item.DefectId);
            if (existingDefect != null)
            {
                // 只更新需要修改的属性,这里以ProjectId为例
                existingDefect.ProjectId = item.ProjectId;
            }
            // 如需支持新增,可保留以下逻辑
            else
            {
                db.Defects.Add(item);
            }
        }
        db.SaveChanges();
        TempData["SM"] = "任务已更新";
    }
    return RedirectToAction("Defectlist");
}

方案二:直接设置实体状态(适合确定无新增的场景)

如果确定提交的都是已存在的实体,可直接标记实体为修改状态:

[HttpPost]
public IActionResult Defectlist(List<Defect> model)
{
    if (ModelState.IsValid)
    {
        foreach(var item in model)
        {
            db.Defects.Attach(item);
            // 标记整个实体为修改状态,或单独标记特定属性
            db.Entry(item).Property(d => d.ProjectId).IsModified = true;
        }
        db.SaveChanges();
        TempData["SM"] = "任务已更新";
    }
    return RedirectToAction("Defectlist");
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 15:00:25