更新EF 6中的现有数据会抛出异常 - “...同一类型的实体具有相同的主键值”。 [英] Updating existing data in EF 6 throws exception - "...entity of the same type already has the same primary key value."

查看:142
本文介绍了更新EF 6中的现有数据会抛出异常 - “...同一类型的实体具有相同的主键值”。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用实体框架6,代码优先,无流畅的映射或Automapper等工具更新记录。

I am trying to update a record using Entity Framework 6, code-first, no fluent mapping or a tool like Automapper.

实体( Employee )具有与其相关联的其他复合属性,如 Addreess (集合),部门

The entity(Employee) has other composite properties associated with it like Addreess(collection), Department

它也从一个名为的用户继承

It is also inherited from a base called User

保存方法如下, _dbContext DbConext 实现

        public bool UpdateEmployee(Employee employee)
        {
            var entity = _dbContext.Employees.Where(c => c.Id == employee.Id).AsQueryable().FirstOrDefault();
            if (entity == null)
            {
                _dbContext.Employees.Add(employee);
            }
            else
            {
                _dbContext.Entry(employee).State = EntityState.Modified; // <- Exception raised here
                _dbContext.Employees.Attach(employee);

            }

            return _dbContext.SaveChanges() > 0;

        }

我不断收到错误:


附加类型的实体失败,因为相同
类型的另一个实体具有相同的主键值。当
使用'附加'方法或将实体的状态设置为
'Unchanged'或'Modified'时,如果图中的任何实体具有
冲突的键值,则可能会发生这种情况。这可能是因为一些实体是新的,并且
尚未收到数据库生成的键值。在这种情况下,使用
添加方法或添加实体状态来跟踪图形,
然后将非新实体的状态设置为不变或修改为
适当的。

Attaching an entity of type 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.

我尝试过以下操作:


  1. 在设置前加入 EntityState.Modified

  2. 添加 AsNoTracking()查询对象是否存在(无例外但DB未更新) - https://stackoverflow.com/a/23228001/ 919426

  3. 使用基础实体 _dbContext.Users 保存而不是Employee实体 - https://stackoverflow.com/a/25575634/919426

  1. Attaching before setting to EntityState.Modified
  2. Adding AsNoTracking() on querying if the object exists(No exception but DB is not updated) - https://stackoverflow.com/a/23228001/919426
  3. Saving using the base entity _dbContext.Users instead of the Employee entity - https://stackoverflow.com/a/25575634/919426



None of which is working for me now.

我的某些解决方案在我的情况下不能工作,我该怎么办?

What could I have gotten wrong for some of those solutions not to work in my situation?

推荐答案

EF已经包含一种方法来映射属性,而不依赖于Automapper,假设您没有导航属性更新:

EF already includes a way to map properties without resorting to Automapper, assuming you do not have navigation properties to update:

public bool UpdateEmployee(Employee employee)
    {
        var entity = _dbContext.Employees.Where(c => c.Id == employee.Id).AsQueryable().FirstOrDefault();
        if (entity == null)
        {
            _dbContext.Employees.Add(employee);
        }
        else
        {
            _dbContext.Entry(entity).CurrentValues.SetValues(employee);              
        }

        return _dbContext.SaveChanges() > 0;

    }

这通常会生成一个更好的SQL语句,因为它只会更新属性已更改。

This usually generates a better SQL statement since it will only update the properties that have changed.

如果您仍然想使用原始方法,您将摆脱实体从上下文中,使用AsNoTracking(不知道为什么在你的情况下没有更新,它应该没有任何效果,所以问题可能是别的)或修改你的查询,以防止它在第一个实体中实现使用类似 bool exists = dbContext.Employees.Any(c => c.Id == employee.Id)之类的东西。

If you still want to use the original method, you'll get rid of entity from the context, either using AsNoTracking (not sure why it didn't update in your case, it should have no effect, so the problem might be something else) or as modifying your query to prevent it from materializing the entity in the first place, using something like bool exists = dbContext.Employees.Any(c => c.Id == employee.Id) for example.

这篇关于更新EF 6中的现有数据会抛出异常 - “...同一类型的实体具有相同的主键值”。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆