如何使用 DbSet 更新数据库

How to update database using DbSet

在我的 MVC 应用程序中,我有一个方法,应该向数据库添加一个实体(如果它不存在),或者更新它(如果它已经在数据库中)

        //...
        var list = _context.CurrencyRepository.Get().ToList();

        foreach (var currency in currencies)
        {                
            var item = list.FirstOrDefault(c => c.CurrencyId == currency.CurrencyId);

            if (item != null)
            {
                _context.CurrencyRepository.Update(currency);                                                          
            }
            else
            {
                _context.CurrencyRepository.Add(currency);
            }
        }

        _context.CommitChanges();
        //...


    public virtual void Update(T entityToUpdate)
    {
        //both lines fail with the same error message
        _dbSet.Attach(entityToUpdate);
        _dbContext.Entry(entityToUpdate).State = EntityState.Modified;
    }

    public virtual T Add(T entity)
    {
        return _dbSet.Add(entity);
    }

    public void CommitChanges()
    {
        _dbContext.SaveChanges();
    }

它适用于添加,但不幸的是我在尝试更新时遇到错误:

Attaching an entity of type 'Currency' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

谁能解释一下我应该如何更新我的数据库?

问题是检索 Currency 项目的查询已经填充了跟踪实体的上下文中的图形。因此,您可以手动更新现有实体的属性(即 item.Name = currency.Name; 等),这相当费力,或者您可以使用 AsNoTracking():

停止被跟踪的实体
var results = db.Set<Currency>().AsNoTracking().Where(...);
//                               ^^^^^^^^^^^^^^