system.invalidoperationException:无法跟踪实体类型的实例,因为{' id'}的另一个具有相同密钥值的实例已经存在

发布于 2025-02-03 03:30:18 字数 8129 浏览 4 评论 0原文

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

这里的问题是,我在crcart服务上对我的帖子方法进行了验证,并且可以正常工作,但是在我的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;

        }

我已经掌握了服务范围,因此这不是问题。请提供帮助,因为我不知道这是什么原因引起的,我有一个截止日期。谢谢。

edit

我的baseerpository我有通用方法

 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();
        }

edgrang> edit> edit 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();
        }

I have an Api deployed on Azure in which I have a CrCart entity. I want to make sure that if there is already a cart associated with a user and a customer with the status "Saved" you can't add more with that status.

The issue here is that I make that validation on my Post method on my CrCart Service and it works fine but on my Put method it doesn't.

Here is the error:

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...

Here is the code for both my Insert and Update methods:

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;

        }

I already have my service Scopped so that's not the issue. Please help because I don't know what it is causing this and I have a deadline for this project. Thanks.

EDIT

My BaseRepository in which I have generic methods

 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();

        }

    }

And my UnitOfWork where I have all the repositories

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();
        }

EDIT 2

Here's the working code which I don't know if it is done properly

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();
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

向地狱狂奔 2025-02-10 03:30:18

有时,如果您使用async使用没有的实体等待等待的实体,以及您的第一个async任务完成之前,您开始调用另一个任务,将投掷此异常

因此,此外,您应该使用实体使用asnotracking()方法,您将不会更改,然后无法保存(只需读取)。

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

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

也许您需要在_unitofwork.crcartrepository.update(cart);

更新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();

Sometimes if you use async methods with entities without await or waiting, and before your first async task finished, you started to call another task, it will throw this exception.

So, in addition, you should use AsNoTracking() method with entities you will not change and then will not save (just read).

UPDATE 1:
In the end of your code check this lines:

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

Maybe you need to add await before _unitOfWork.CrCartRepository.Update(cart);

UPDATE 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);
}

or you can replace it with AsNoTrackingWithIdentityResolution() if you have newest EF CORE.

UPDATE 3
Also try this:

_context.Entry(entity).State = EntityState.Modified;
_context.SaveChanges();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文