问题描述
我正在尝试使用 Entity Framework 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
(collection)、Department
The entity(Employee
) has other composite properties associated with it like Addreess
(collection), Department
它也继承自一个名为 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;
}
我不断收到错误:
附加一个类型的实体失败,因为另一个相同的实体type 已经具有相同的主键值.这可能发生在使用附加"方法或将实体的状态设置为未更改"或已修改",如果图中的任何实体具有键值冲突.这可能是因为一些实体是新的并且尚未收到数据库生成的键值.在这种情况下使用'Add' 方法或 'Added' 实体状态来跟踪图形和然后将非新实体的状态设置为未更改"或已修改"为合适.
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.
我尝试了以下方法:
- 在设置为
EntityState.Modified
之前附加 - 在查询对象是否存在时添加
AsNoTracking()
(无异常但数据库未更新) - https://stackoverflow.com/a/23228001/919426 - 使用基本实体
_dbContext.Users
而不是 Employee 实体进行保存 - https://stackoverflow.com/a/25575634/919426
- Attaching before setting to
EntityState.Modified
- Adding
AsNoTracking()
on querying if the object exists(No exception but DB is not updated) - https://stackoverflow.com/a/23228001/919426 - Saving using the base entity
_dbContext.Users
instead of the Employee entity - https://stackoverflow.com/a/25575634/919426
现在这些都不适合我.
如果其中一些解决方案不适用于我的情况,我会做错什么?
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.
如果您仍想使用原始方法,您将从上下文中删除 entity
,或者使用 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 中的现有数据会引发异常 - “...相同类型的实体已经具有相同的主键值."的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!