EF Core报错:同一主键Activity实例已被跟踪,求解决办法
解决EF Core实体跟踪冲突错误
问题场景
更新数据库Activity记录时触发如下错误:
The instance of entity type 'Activity' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked
相关代码:
public async Task<bool> AddUpdateAsync(Activity objActivity) { try { using (var _db = _factory.CreateDbContext()) { if (objActivity.Id == 0) { // CODE TO ADD NEW HERE } else { var DbActivity = await GetByIdAsync(objActivity.Id); PropertyInfo[] properties = typeof(Activity).GetProperties(); foreach (var property in properties) { property.SetValue(DbActivity, property.GetValue(objActivity)); } _db.Update(DbActivity); await _db.SaveChangesAsync(); } } return true; } catch (Exception ex) { return false; } } public async Task<Activity> GetByIdAsync(int Id) { using (var _db = _factory.CreateDbContext()) { return await _db.Activities.Include(x => x.Room).Include(x => x.Debtor).SingleAsync(x => x.Id == Id); } }
错误原因
GetByIdAsync方法创建了独立的DbContext实例,查询返回的DbActivity会被这个上下文跟踪;回到AddUpdateAsync的_db上下文时,调用_db.Update(DbActivity)会尝试将该实体附加到当前上下文,由于实体已被另一个上下文跟踪,EF Core触发跟踪冲突。
解决方案
方案1:复用同一个DbContext(推荐)
修改GetByIdAsync,让它接收外部传入的DbContext,避免创建新上下文:
public async Task<Activity> GetByIdAsync(int Id, DbContext _db) { return await _db.Activities.Include(x => x.Room).Include(x => x.Debtor).SingleAsync(x => x.Id == Id); }
在AddUpdateAsync中调用时传入当前上下文:
var DbActivity = await GetByIdAsync(objActivity.Id, _db);
这样DbActivity始终由同一个上下文跟踪,后续更新操作不会冲突。
方案2:关闭查询的实体跟踪
如果不想修改GetByIdAsync的参数,可以在查询时关闭跟踪,返回无跟踪实体:
public async Task<Activity> GetByIdAsync(int Id) { using (var _db = _factory.CreateDbContext()) { return await _db.Activities.Include(x => x.Room).Include(x => x.Debtor) .AsNoTracking() // 关闭实体跟踪 .SingleAsync(x => x.Id == Id); } }
返回的DbActivity不属于任何上下文,当前_db.Update可以正常附加并跟踪它。
方案3:直接附加实体并标记修改(高效)
如果不需要加载Room和Debtor关联实体,可直接将传入的objActivity附加到上下文并标记为修改状态,省去查询步骤:
else { _db.Attach(objActivity); _db.Entry(objActivity).State = EntityState.Modified; await _db.SaveChangesAsync(); }
注意:这种方式不处理关联实体的更新,若需更新关联数据,需单独处理。
内容的提问来源于stack exchange,提问作者Jeremy
相关产品推荐
相关产品推荐

