System.InvalidOperationException: 无法跟踪实体类型的实例,因为已存在具有与 {'Id'} 相同键值的另一个实例

System.InvalidOperationException: The instance of entity type cannot be tracked because another instance with the same key value for {'Id'} is already

我在 Azure 上部署了一个 Api,其中有一个 CrCart 实体。我想确保如果已经有一个与状态为“已保存”的用户和客户相关联的购物车,您将无法添加更多具有该状态的内容。

这里的问题是我在我的 CrCart 服务上对我的 Post 方法进行了验证并且它工作正常但在我的 Put 方法上它没有。

这里是错误:

System.InvalidOperationException: The instance of entity type 'CrCart' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using...

这是我的 InsertUpdate 方法的代码:

public async Task Insert(CrCart cart)
        {
            var user = await _unitOfWork.CrUserRepository.GetById(cart.IdUser);
            var customer = await _unitOfWork.CrCustomerRepository.GetById(cart.IdCustomer);

            var carts = _unitOfWork.CrCartRepository.GetAll();
            carts = carts.Where(x => x.IdCustomer == cart.IdCustomer && x.Status == "Saved" && x.IdUser == cart.IdUser);

            if (user == null)
            {
                throw new BusinessException("El usuario introducido no existe");
            }

            if (customer == null)
            {
                throw new BusinessException("El cliente introducido no existe");
            }

            if (carts.Count() >= 1 && cart.Status == "Saved") {

                throw new BusinessException("Ya existe un carrito con estado -Saved- asignado al cliente " +
                    customer.Name);
            }   

            await _unitOfWork.CrCartRepository.Insert(cart);
            await _unitOfWork.SaveChangesAsync();
        }

        public async Task<bool> Update(CrCart cart)
        {
            var user = await _unitOfWork.CrUserRepository.GetById(cart.IdUser);
            var customer = await _unitOfWork.CrCustomerRepository.GetById(cart.IdCustomer);

            var carts = _unitOfWork.CrCartRepository.GetAll();
            carts = carts.Where(x => x.IdCustomer == cart.IdCustomer && x.Status == "Saved" && x.IdUser == cart.IdUser);

            if (user == null)
            {
                throw new BusinessException("El usuario introducido no existe");
            }

            if (customer == null)
            {
                throw new BusinessException("El cliente introducido no existe");
            }

            if (carts.Count() >= 1 && cart.Status == "Saved")
            {

                throw new BusinessException("Ya existe un carrito con estado -Saved- asignado al cliente " +
                    customer.Name);
            }

            _unitOfWork.CrCartRepository.Update(cart);
            await _unitOfWork.SaveChangesAsync();

            return true;

        }

我的服务已经 Scopped,所以这不是问题所在。请帮忙,因为我不知道是什么原因造成的,而且我有这个项目的最后期限。谢谢。

编辑

我的 BaseRepository 我有通用方法

 public class BaseRepository<T> : IBaseRepository<T> where T: BaseEntity
    {
        private readonly db_crijoyaContext _context;
        protected readonly DbSet<T> _entities;

        public BaseRepository(db_crijoyaContext context)
        {
            _context = context;
            _entities = context.Set<T>();
        }

        public IEnumerable<T> GetAll()
        {
           return _entities.AsEnumerable();
        }

        public async Task<T> GetById(int id)
        {
            return await _entities.FindAsync(id);
        }

        public async Task Insert(T entity)
        {
            await _entities.AddAsync(entity);
            
            //await _context.SaveChangesAsync();
        }

        public void Update(T entity)
        {
            
            _entities.Update(entity);
            
            //await _context.SaveChangesAsync();
        }

        public async Task Delete(int id)
        {
            T entity = await GetById(id);
            _entities.Remove(entity);

            //await _context.SaveChangesAsync();

        }

    }

还有我的 UnitOfWork 我拥有所有存储库

public class UnitOfWork : IUnitOfWork 
    {
        private readonly db_crijoyaContext _context;
        private readonly ICrProductRepository _productRepsitory;
        private readonly IBaseRepository<CrCompany> _companyRepository;
        private readonly IBaseRepository<CrCategory> _categoryRepository;
        private readonly IBaseRepository<CrCart> _cartRepository;
        private readonly IBaseRepository<CrCustomer> _customerRepository;
        private readonly IBaseRepository<CrUser> _userRepository;
        private readonly IBaseRepository<CrOrder> _orderRepository;
        private readonly IBaseRepository<CrCity> _cityRepository;
        private readonly ICrUserInfoRepository _userInfoRepository;
        private readonly ICrCountryRepository _countryRepository;

        public UnitOfWork(db_crijoyaContext context)
        {
            _context = context;
        }

        public ICrProductRepository CrProductRepository => _productRepsitory ?? new CrProductRepository(_context);
        public IBaseRepository<CrCategory> CrCategoryRepository => _categoryRepository ?? new BaseRepository<CrCategory>(_context);
        public IBaseRepository<CrCompany> CrCompanyRepository => _companyRepository ?? new BaseRepository<CrCompany>(_context);
        public IBaseRepository<CrUser> CrUserRepository => _userRepository ?? new BaseRepository<CrUser>(_context);
        public IBaseRepository<CrCart> CrCartRepository => _cartRepository ?? new BaseRepository<CrCart>(_context);
        public IBaseRepository<CrCustomer> CrCustomerRepository => _customerRepository ?? new BaseRepository<CrCustomer>(_context);
        public IBaseRepository<CrOrder> CrOrderRepository => _orderRepository ?? new BaseRepository<CrOrder>(_context);
        public IBaseRepository<CrCity> CrCityRepository => _cityRepository ?? new BaseRepository<CrCity>(_context);
        public ICrUserInfoRepository CrUserInfoRepository => _userInfoRepository ?? new CrUserInfoRepository(_context);
        public ICrCountryRepository CrCountryRepository => _countryRepository ?? new CrCountryRepository(_context);

        public void Dispose()
        {
            if(_context != null)
            {
                _context.Dispose();
            }
        }

        public void SaveChanges()
        {
            _context.SaveChanges();
        }

        public async Task SaveChangesAsync()
        {
            await _context.SaveChangesAsync();
        }

编辑 2

这是工作代码,我不知道它是否正确完成

public async Task<bool> Update(CrCart cart)
        {
            var user = await _unitOfWork.CrUserRepository.GetById(cart.IdUser);
            var customer = await _unitOfWork.CrCustomerRepository.GetById(cart.IdCustomer);

            var carts = _unitOfWork.CrCartRepository.GetAllWithNoTracking();
            carts = carts.Where(x => x.IdCustomer == cart.IdCustomer && x.Status == "Saved" && x.IdUser == cart.IdUser);

            if (user == null)
            {
                throw new BusinessException("El usuario introducido no existe");
            }

            if (customer == null)
            {
                throw new BusinessException("El cliente introducido no existe");
            }

            if (carts.Count() >= 1 && cart.Status == "Saved")
            {

                throw new BusinessException("Ya existe un carrito con estado -Saved- asignado al cliente " +
                    customer.Name);
            }

             _unitOfWork.CrCartRepository.Update(cart);
            await _unitOfWork.SaveChangesAsync();

            return true;

        }

public IEnumerable<T> GetAllWithNoTracking()
        {
            return _entities.AsNoTracking().AsEnumerable();
        }

有时,如果您在没有 await 或等待的情况下对实体使用 async 方法,并且在您的第一个 async 任务完成之前,您开始调用另一个任务,它将抛出此 exception.

因此,此外,您应该对不会更改的实体使用 AsNoTracking() 方法,也不会保存(只读)。

更新 1: 在您的代码末尾检查以下行:

_unitOfWork.CrCartRepository.Update(cart);
await _unitOfWork.SaveChangesAsync(); 

也许你需要在_unitOfWork.CrCartRepository.Update(cart);

之前加上await

更新 2:

public IEnumerable<T> GetAllWithNoTracking()
{
   return _entities.AsNoTracking().AsEnumerable();
}

public async Task<T?> GetByIdWithNoTracking(int id)
{
    return await _entities.AsNoTracking().FirstOrDefault(x => x.id == id);
}

或者如果您有最新的 EF CORE,您可以将其替换为 AsNoTrackingWithIdentityResolution()

更新 3 也试试这个:

_context.Entry(entity).State = EntityState.Modified;
_context.SaveChanges();