EF中附加已经存在的实体的方法。
一、错误
EF中附加类型“**”的实体失败,因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为。这可能是因为某些实体是新的并且尚未接收数据库生成的键值。在此情况下,使用 "Add" 方法或者 "Added" 实体状态跟踪该图形,然后将非新实体的状态相应设置为 "Unchanged" 或 "Modified"。
二、错误原因
1.直接使用了查询出来的实体,然后附加,可能出现此问题,
解决办法:在查询语句中添加.AsNoTracking()(即查询结果上下文不进行跟踪);如 DbContext.Set<T>().AsNoTracking();
2.在使用 DbContext.Entry<T>(t).State = EntityState.Modified; 使用 EntityState.Modified后会自动跟踪实体,如果再次附加也会出现此问题。
解决办法:
直接查找上下文中是否存在此实体,如果存在则移除,然后再进行操作,此方法在大部分情况下有效。
/// <summary>
/// 如果上下文中存在对象则移除
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public bool Exists(T entity)
{
ObjectContext _ObjContext = ((IObjectContextAdapter)DbContext).ObjectContext;
ObjectSet<T> _ObjSet = _ObjContext.CreateObjectSet<T>();
var entityKey = _ObjContext.CreateEntityKey(_ObjSet.EntitySet.Name, entity);
Object foundEntity;
var exists = _ObjContext.TryGetObjectByKey(entityKey, out foundEntity);
// TryGetObjectByKey attaches a found entity
// Detach it here to prevent side-effects
if (exists)
{
_ObjContext.Detach(foundEntity);
}
return (exists);
}