无法跟踪实体类型的实例,因为跟踪了另一个具有相同键值的实例

时间:2021-03-13 11:50:44

标签: .net entity-framework-core

尝试从数据库中删除 PendingUser 时,出现错误:

<块引用>

'实体类型 'PendingUser' 的实例无法被跟踪,因为 另一个具有键值 '{UserId: 123}' 的实例已经在 跟踪。附加现有实体时,确保只有一个实体 附加具有给定键值的实例。'

  public async Task RemoveAsync(PendingUser pendingUser)
  {
     _context.PendingUsers.Remove(pendingUser);
     await _context.SaveChangesAsync();
  }

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

默认情况下,DBContext 作为 loadBytes 注入。这种做法有助于保持跟踪尽可能干净。

然而,这可能是一个简单的跟踪问题。

如果 scoped 是一个输入(如 DTO)并且没有从上下文中恢复(使用跟踪),您需要在删除它之前附加它。

波纹管,一些建议,你可以使用作为删除行为:

pendingUser

完整示例here
也可以查看依赖注入策略here

在这种特殊情况下,public abstract class Repository<TEntity, TId> : IRepository<TEntity, TId> where TEntity : Entity<TId> where TId : struct { private readonly DbSet<TEntity> _dbSet; protected Repository(DbContext dbDbContext) { _dbSet = dbDbContext.Set<TEntity>(); } public virtual void Delete(TId id) { var entity = GetById(id, asTracking: true); if (entity is null) return; _dbSet.Remove(entity); } public virtual void Delete(TEntity entity) { if (entity is null) return; _dbSet.Attach(entity); _dbSet.Remove(entity); } public virtual async Task DeleteAsync(TId id, CancellationToken cancellationToken) { var entity = await GetByIdAsync(id, cancellationToken, asTracking: true); if (entity is null) return; _dbSet.Remove(entity); } public virtual async Task DeleteAsync(TEntity entity, CancellationToken cancellationToken) { if (entity is null) return; await Task.Run(() => Delete(entity), cancellationToken); } } 和其他 SaveChanges 行为由 DBContext 封装。由服务层提供事务控制。

UnitOfWork

Service abstractions
UnitOfWork