我使用Unity of Work和CodeCamper的通用存储库。
更新实体,通用仓库有:
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; }
更新实体时,我收到以下错误:
附加信息:附加类型&#39; X&#39;的实体。失败,因为同一类型的另一个实体已具有相同的主键值。 使用&#39;附加&#39;方法或将实体的状态设置为“未更改”#39;或者&#39;修改&#39;如果图中的任何实体具有冲突的键值。 这可能是因为某些实体是新的并且尚未收到数据库生成的键值。 在这种情况下,请使用&#39;添加&#39;方法或“添加”#39;实体状态跟踪图形,然后将非新实体的状态设置为“未更改”。或者&#39;修改&#39;酌情。
当它是您调用存储库的第一个方法时,更新正常。 (我创建了一个ID已存在于DB中的实体并调用了更新。)
在更新实体之前获取实体时,更新不起作用。 (例如,我得到一个实体X,将其转换为DTO,然后在UI中更改一些值, 然后调用一个web api,用新的值创建一个实体X. 调用存储库的更新。)
有什么想法可以避免这种情况吗? 当你有一个CRUD应用程序时,你总是在更新之前调用get。
答案 0 :(得分:2)
我使用自己的附加方法:
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("...");
}
}
答案 1 :(得分:0)
我有同样的问题。问题出在混合背景下。在context1中从DB读取实体时。然后,如果您可以使用contex2(具有自己的实体缓存的相同上下文的其他实例)更新此实体。这可能会引发异常。
请检查参考资料:
通过context1: 从DB
读取带有引用的entity2的entity1通过context2: 从DB读取entity2。然后更新entity1(从context1引用entity2)。
当您尝试将带有引用的entity2的entity1附加到context2时,抛出异常,因为entity2已存在于context2中。
解决方案仅使用一个上下文进行此操作。