Entity framework 将实体附加到上下文失败,因为它已存在
我使用CodeCamper的统一工作和通用存储库 要更新实体,一般回购协议有:Entity framework 将实体附加到上下文失败,因为它已存在,entity-framework,repository-pattern,Entity Framework,Repository Pattern,我使用CodeCamper的统一工作和通用存储库 要更新实体,一般回购协议有: public virtual void Update(T entity) { DbEntityEntry dbEntityEntry = DbContext.Entry(entity); if (dbEntityEntry.State == EntityState.Detached) { DbSet.Attach(entity);
public virtual void Update(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State == EntityState.Detached)
{
DbSet.Attach(entity);
}
dbEntityEntry.State = EntityState.Modified;
}
web api方法:
public HttpResponseMessage Put(MyEditModel editModel)
{
var model = editModel.MapToMyEntity();
_myManager.Update(model);
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
更新方法:
public void Update(MyEntity model)
{
Uow.MyEntities.Update(model);
Uow.Commit();
}
在工作单元中:
IRepository<MyEntity> MyEntities { get; }
i阳性髓质{get;}
更新实体时,我收到以下错误:
其他信息:附加“X”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。
如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。
这可能是因为某些实体是新的,尚未收到数据库生成的键值。
在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”
当你有一个CRUD应用程序时,你总是在更新之前调用get 我也有同样的问题。问题的背景是复杂的。当您在context1中从DB读取实体时。然后,如果您可以使用contex2(具有自己的实体缓存的相同上下文的其他实例)更新此实体。这可能引发异常 请检查参考资料: 按上下文1: 从数据库中读取具有引用的entity2的entity1 按上下文2: 从数据库读取entity2。然后更新entity1(使用context1中引用的entity2) 当您尝试将引用了entity2的entity1附加到context2时,会引发异常,因为context2中已经存在entity2
解决方案是仅为此操作使用一个上下文。我正在使用自己的附加方法:
public void Attach<E>(ref E entity)
{
if (entity == null)
{
return;
}
try
{
ObjectStateEntry entry;
bool attach = false;
if (ObjectStateManager.TryGetObjectStateEntry(CreateEntityKey(entitySetName, entity), out entry))
{
attach = entry.State == EntityState.Detached;
E existingEntityInCache = (E)entry.Entity;
if (!existingEntityInCache.Equals(entity))
{
existingEntityInCache.SetAllPropertiesFromEntity(entity);
}
entity = existingEntityInCache;
}
else
{
attach = true;
}
if (attach)
objectContext.AttachTo(entitySetName, entity);
}
catch (Exception ex)
{
throw new Exception("...");
}
}
公共作废附加(参考E实体)
{
if(实体==null)
{
返回;
}
尝试
{
ObjectStateEntry条目;
bool-attach=false;
if(ObjectStateManager.TryGetObjectStateEntry(CreateEntityKey(entitySetName,entity),out条目))
{
attach=entry.State==EntityState.Detached;
E existingEntityInCache=(E)entry.Entity;
如果(!existingEntityInCache.Equals(实体))
{
existingEntityInCache.SetAllPropertiesFromEntity(实体);
}
实体=现有实体incache;
}
其他的
{
附加=真;
}
如有的话(附上)
AttachTo(entitySetName,entity);
}
捕获(例外情况除外)
{
抛出新异常(“…”);
}
}
我认为Entry
所做的查找是基于.Net引用的,因此出现了“问题”。相反,您应该首先尝试在本地
集合中查找实体。我读过类似“在上下文中分离原始实体,然后附加新的/更新的实体”的内容,但我不喜欢这种解决方案。只要执行获取
,实体就会加载到您的上下文中。由于更新在获取
后失败,因此您必须尝试以某种方式附加重复的实体。一旦您将实体映射到DTO,您是否可以尝试在get
之后分离实体?@Filip您是否可以发布处理此问题的web api代码:“然后调用web api,使用新值创建实体X并调用存储库的更新”?数据库中的主键是否设置为自动增量?