调用UpdateVergadering时出现实体跟踪冲突错误求助
问题解决:实体跟踪冲突错误
错误信息翻译
System.InvalidOperationException: 实体类型'Bestuurslid'的实例无法被跟踪,因为另一个具有相同键值{'Id'}的实例已经被跟踪。附加现有实体时,请确保每个给定键值只附加一个实体实例。
问题根源
调用UpdateVergadering时,传入的Vergadering对象关联的Bestuurslid实体,已被另一个DbContext实例跟踪——哪怕查询方法用了NoTracking,只要这个对象在其他操作中被其他上下文跟踪过,或是修改关联实体时引入了已跟踪实例,就会触发冲突。
解决方案
方案1:局部更新(推荐)
仅更新Vergadering自身字段,不处理关联实体,避免整个对象树的跟踪冲突:
public async ValueTask<int> UpdateVergadering(Vergadering vergadering) { using var dbContext = _factory.CreateDbContext(); // 从数据库获取原始实体 var existingVergadering = await dbContext.Set<Vergadering>() .FindAsync(vergadering.Id); if (existingVergadering == null) return 0; // 可根据业务需求改为抛出异常 // 手动复制需要更新的属性 existingVergadering.Naam = vergadering.Naam; existingVergadering.Datum = vergadering.Datum; // 添加其他需要更新的字段 return await dbContext.SaveChangesAsync(); }
方案2:手动处理关联实体的跟踪状态
若必须更新关联实体,逐个检查并处理跟踪状态:
public async ValueTask<int> UpdateVergadering(Vergadering vergadering) { using var dbContext = _factory.CreateDbContext(); // 处理关联的Bestuurslid实体 foreach (var bestuurslid in vergadering.Bestuursleden) { var trackedEntity = dbContext.Find<Bestuurslid>(bestuurslid.Id); if (trackedEntity != null) { // 已跟踪,将新值复制到已跟踪实例 dbContext.Entry(trackedEntity).CurrentValues.SetValues(bestuurslid); } else { // 未跟踪,附加为未修改状态 dbContext.Attach(bestuurslid); } } // 处理Vergadering自身 var trackedVergadering = dbContext.Find<Vergadering>(vergadering.Id); if (trackedVergadering != null) { dbContext.Entry(trackedVergadering).CurrentValues.SetValues(vergadering); } else { dbContext.Update(vergadering); } return await dbContext.SaveChangesAsync(); }
方案3:确保传入的实例处于无跟踪状态
如果传入的Vergadering来自其他DbContext,先解除跟踪:
// 在调用UpdateVergadering之前执行 otherDbContext.Entry(vergadering).State = EntityState.Detached; foreach (var bl in vergadering.Bestuursleden) { otherDbContext.Entry(bl).State = EntityState.Detached; } await vergaderingRepository.UpdateVergadering(vergadering);
内容的提问来源于stack exchange,提问作者Jeremy
相关产品推荐
相关产品推荐

