我正在尝试使用 Entity Framework 6、代码优先、没有流畅的映射或 Automapper 等工具来更新记录。
实体(Employee
)具有与其相关的其他复合属性,例如Addreess
(收藏),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 已经具有相同的主键值。这可能发生在以下情况:
使用“附加”方法或将实体的状态设置为
如果图表中的任何实体有,则为“未更改”或“已修改”
冲突的关键值。这可能是因为有些实体是新的并且
尚未收到数据库生成的键值。在这种情况下使用
“添加”方法或“已添加”实体状态来跟踪图形和
然后将非新实体的状态设置为“未更改”或“已修改”,如下所示
合适的。
我已经尝试过以下方法:
- 设置为之前连接
EntityState.Modified
- Adding
AsNoTracking()
查询对象是否存在(没有例外,但数据库未更新) -https://stackoverflow.com/a/23228001/919426
- 使用基础实体保存
_dbContext.Users
而不是 Employee 实体 -https://stackoverflow.com/a/25575634/919426
现在这些都不适合我。
我可能犯了什么错误,导致其中一些解决方案在我的情况下不起作用?
EF 已经包含了一种无需借助 Automapper 即可映射属性的方法,假设您没有导航属性更新:
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 语句,因为它只会更新已更改的属性。
如果你还想用原来的方法,就去掉entity
从上下文来看,要么使用 AsNoTracking (不确定为什么它在你的情况下没有更新,它应该没有效果,所以问题可能是其他的),要么修改你的查询以防止它首先具体化实体,使用类似的东西bool exists = dbContext.Employees.Any(c => c.Id == employee.Id)
例如。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)