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

EF Core调用SaveChanges时向关联表插入重复记录问题排查求助

问题根源

  • 你的Schedule模型未显式声明外键字段,且前端提交的StorageDataInfo未携带ID值:当前视图仅提交了StorageDataInfo的Name/LicensePlate/BIN三个字段,POST后绑定的StorageDataInfo对象ID为默认值0,EF Core无法识别这是已存在的实体,会将其标记为Added状态同步插入。
  • DbContext未追踪传入的StorageDataInfo对象:你从前端接收的StorageDataInfo没有被当前请求的DbContext追踪,直接将其赋值给新增的Schedule导航属性时,_context.Schedule.Add方法会将整个关联对象图全部标记为新增,导致重复插入tblStorageData表。

修复步骤

1. 完善模型声明,显式添加外键

在Schedule类中增加外键字段,明确关联关系:

[Table("tblSchedule")]
public class Schedule
{
    [Required]
    public int ID { get; set; }
    [Required]
    public DateTime ScheduleDateTime { get; set; }
    public bool Confirmed { get; set; } = false;
    // 新增显式外键字段
    public int StorageDataInfoID { get; set; }
    public StorageData StorageDataInfo { get; set; }
}

2. 视图补充StorageDataInfo.ID隐藏字段

修改cshtml文件,在表单中增加ID的隐藏域,确保POST时能携带已有存储数据的ID:

@Html.HiddenFor(m => m.StorageDataInfo.ID)
@Html.HiddenFor(m => m.StorageDataInfo.Name)
@Html.HiddenFor(m => m.StorageDataInfo.LicensePlate)
@Html.HiddenFor(m => m.StorageDataInfo.BIN)

3. 修改新增逻辑,避免插入关联实体

推荐直接通过外键关联,无需赋值导航属性,从根源避免误插入:

public int AddSchedule(Schedule model)
{
    if (CheckSchedule(model.ScheduleDateTime) >= 4)
    {
        return 0;
    }
    else
    {
        Schedule sch = new Schedule()
        {
            ScheduleDateTime = model.ScheduleDateTime,
            // 直接赋值外键,不赋值导航属性
            StorageDataInfoID = model.StorageDataInfo.ID
        };
        _context.Schedule.Add(sch);
        _context.SaveChanges();
        return 1;
    }
}

如果需要保留导航属性赋值的写法,可以手动标记StorageDataInfo为已存在状态:

Schedule sch = new Schedule()
{
    ScheduleDateTime = model.ScheduleDateTime,
    StorageDataInfo = model.StorageDataInfo
};
_context.Schedule.Add(sch);
// 手动标记关联实体为未修改,不会插入新数据
_context.Entry(sch.StorageDataInfo).State = EntityState.Unchanged;
_context.SaveChanges();

可选优化

为了避免前端篡改ID导致数据异常,可以在新增前先校验StorageDataInfo.ID是否在数据库中存在:

var existStorage = _context.StorageData.FirstOrDefault(s => s.ID == model.StorageDataInfo.ID);
if(existStorage == null) {
    // 非法ID,返回错误
    return -1;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:45:02