EF Core添加关联实体时触发DbUpdateConcurrencyException错误
EF Core 添加关联实体触发 DbUpdateConcurrencyException 的原因与解决办法
原因分析
- 主实体无跟踪导致子实体未被识别:如果仓储获取
Tutor时使用了AsNoTracking(),该实体处于EF无跟踪状态。此时向Tutor.Availability集合添加新Availability,EF不会自动跟踪这个子实体,保存时既不会执行插入操作,还可能因误判Tutor需要更新(但无跟踪实体无法匹配数据库行),触发“预期影响1行实际0行”的并发异常。 - 内存集合变更未通知EF上下文:若
AddAvailability方法仅在内存集合中添加对象,没有让EF上下文感知到这个新增实体,EF无法识别这是需要持久化的新数据。 - 上下文实例不统一:获取
Tutor的仓储上下文和后续操作的上下文不是同一个实例,新创建的Availability不在有效上下文的跟踪范围内,EF不会处理该实体。
正确处理方案
方案1:确保主实体处于跟踪状态
检查仓储获取Tutor的代码,移除AsNoTracking(),保留EF对实体的跟踪:
// 仓储中获取Tutor的示例代码(保留跟踪) public Tutor GetTutorById(int id) { return _context.Tutors.Include(t => t.Availability).FirstOrDefault(t => t.Id == id); }
此时直接向Tutor.Availability添加新Availability,EF会自动跟踪子实体,调用SaveChanges()时会正常执行插入。
方案2:手动将子实体纳入上下文跟踪
若业务必须使用无跟踪Tutor,添加子实体后手动将其标记为新增:
var tutor = _tutorRepository.GetTutorByIdAsNoTracking(1); var newAvailability = new Availability { TutorId = tutor.Id, // 其他属性初始化 }; tutor.AddAvailability(newAvailability); // 手动让EF跟踪子实体 _context.Availabilities.Add(newAvailability); _context.SaveChanges();
方案3:在AddAvailability中集成跟踪逻辑
修改Tutor的AddAvailability方法,直接关联上下文标记实体状态:
// Tutor实体类中的方法 public void AddAvailability(Availability availability, AppDbContext context) { Availability.Add(availability); context.Entry(availability).State = EntityState.Added; }
调用时传入当前上下文,确保EF识别新增实体。
方案4:用Update方法重新跟踪无跟踪实体
如果Tutor是无跟踪状态,可通过Update让EF重新跟踪实体及关联子实体:
var tutor = _tutorRepository.GetTutorByIdAsNoTracking(1); var newAvailability = new Availability { /* 属性初始化 */ }; tutor.AddAvailability(newAvailability); _context.Update(tutor); // 重新跟踪Tutor及其关联的新增实体 _context.SaveChanges();
注意:此方法会将Tutor标记为已修改,若Tutor无实际变更,会产生多余的更新语句,需根据场景选择。
内容的提问来源于stack exchange,提问作者Mush-A
相关产品推荐
相关产品推荐

