EF更新数据库时TblCompany实体跟踪冲突问题求助
解决Entity Framework实体跟踪冲突问题
问题核心原因
报错的本质是:你传入的overridee对象中的TblCompany实体,与当前DbContext中已在跟踪的同主键(paramID=2)的TblCompany实例重复。直接将外部传入的关联实体(如overridee.Company)赋值给上下文已加载的tempOverridee,EF的跟踪机制会检测到同一个主键对应两个不同的实体实例,从而触发冲突。
可行解决方案
方案1:仅赋值外键ID(推荐)
EF会自动通过外键维护关联关系,不需要手动赋值关联实体对象,只设置外键ID即可彻底避免跟踪冲突。
修改后的核心代码:
else { tempOverridee.paramPct = overridee.paramPct; // 仅赋值外键ID,不直接操作Product/Company实体对象 tempOverridee.ProductId = overridee.ProductId; tempOverridee.CompanyId = overridee.CompanyId; tempOverridee.paramOverriderId = overridee.paramOverriderId; tempOverridee.paramDesc = overridee.paramDesc; tempOverridee.paramSalesPersonID = overridee.paramSalesPersonID; tempOverridee.paramUpdatedOn = DateTime.Now; _db.SaveChanges(); // 若返回结果需要包含关联实体,可手动加载(可选) _db.Entry(tempOverridee).Reference(o => o.Company).Load(); _db.Entry(tempOverridee).Reference(o => o.Product).Load(); return new ServiceResponse<TblOverridee?> { Data = tempOverridee, Time = DateTime.Now, IsSuccess = true, Message = "TblOverridee Updated" }; }
方案2:需更新关联实体属性时,先处理跟踪状态
如果确实需要更新TblCompany的属性,要先确保当前上下文只有一个该ID的实体实例被跟踪:
else { if (overridee.Company != null && overridee.CompanyId > 0) { // 检查上下文本地缓存中是否已跟踪该Company var trackedCompany = _db.TblCompany.Local.FirstOrDefault(c => c.paramID == overridee.CompanyId); if (trackedCompany != null) { // 已跟踪则直接更新属性 trackedCompany.CompanyName = overridee.Company.CompanyName; // 替换为实际要更新的属性 } else { // 未跟踪则附加实体并标记为修改状态 _db.Attach(overridee.Company); _db.Entry(overridee.Company).State = EntityState.Modified; } // 给tempOverridee设置外键即可 tempOverridee.CompanyId = overridee.CompanyId; } // 其他属性赋值逻辑 tempOverridee.paramPct = overridee.paramPct; tempOverridee.ProductId = overridee.ProductId; tempOverridee.paramOverriderId = overridee.paramOverriderId; tempOverridee.paramDesc = overridee.paramDesc; tempOverridee.paramSalesPersonID = overridee.paramSalesPersonID; tempOverridee.paramUpdatedOn = DateTime.Now; _db.SaveChanges(); return new ServiceResponse<TblOverridee?> { Data = tempOverridee, Time = DateTime.Now, IsSuccess = true, Message = "TblOverridee Updated" }; }
之前尝试未生效的原因
- 你分离的是
_db.TblCompany.Find返回的实例,但传入的overridee.Company可能是反序列化生成的独立实例,上下文可能已经在跟踪这个传入的实例,因此分离查询到的实例无法解决冲突。 - 直接将查询到的
cmpny赋值给overridee.Company,但tempOverridee已被上下文跟踪,若overridee的其他关联实体仍存在跟踪问题,冲突依然会触发。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

