EF Core调用UserManager.UpdateAsync触发同Id实体已被跟踪异常
EF Core 实体跟踪冲突问题
我知晓该类问题此前已有相关提问,但现有解决方案均未解决我的问题,触发的异常信息如下:
实体类型'User'的实例无法被跟踪,因为另一个具有相同{'Id'}键值的实例已处于被跟踪状态。附加现有实体时,请确保仅附加一个具有指定键值的实体实例。
问题复现
调用Identity框架的更新方法时触发了该异常,对应代码如下:
await _userManager.UpdateAsync(user);
我也尝试过使用仓储模式实现更新,该方式可以正常完成更新操作,对应代码如下:
public async Task UpdateAsync(TEntity entity) { _dbSet.Update(entity); _context.Entry(entity).State = EntityState.Modified; }
但使用Attach方法实现更新时,无法通过导航属性更新与User类关联的数据,对应代码如下:
public async Task UpdateAsync(TEntity entity) { _dbSet.Attach(entity); _context.Entry(entity).State = EntityState.Modified; }
我不清楚哪里操作有误,按预期Identity框架的相关类应当可以正常运行。
问题根因定位(更新)
最终定位到问题根因有两点:
- 查询时一次性通过
Include加载了主表关联的所有附属表数据(例如查询Users时关联加载Categories表数据)并直接操作关联数据,这不是正确的实现方式。开发时应当遵循按需查询原则:如果需要更新分类数据,不应通过主实体的关联对象操作,仅需从数据库查询当前要处理的数据即可,否则极易引发此类跟踪错误。 - DTO配置不合理,DTO中存储了同一User的多个实例,最终引发跟踪冲突。
错误实现示例
不推荐的DTO定义方式
class ExampleCategoryDTO { public int Id { get; set; } public string Name { get; set; } public IList<User> Users { get; set; } // 错误定义 }
错误的数据操作方式
var tmp = context.Include(x => x.Categories).Users.ToList(); // 直接修改tmp变量中关联的分类数据 context.Update(tmp); context.SaveChanges();
感谢所有尝试提供帮助的人,很抱歉最初提问时未提供足够信息(当时我也未定位到问题的产生根源)
内容的提问来源于stack exchange,提问作者Arbross
相关产品推荐
相关产品推荐

