我试图解决EF 6上的乐观并发控制问题。我目前想要捕获DBUpdateConcurrencyException
然后刷新实体。但是我现在得到这个例外:
System.InvalidOperationException:索引为0的元素 要刷新的对象集合具有null EntityKey属性值 或者没有附加到此ObjectStateManager。
以下是显示目的的代码的简化版本:
using (var dbContextTransaction = dbContext.Database.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
try
{
dbContext.Commit();
}
catch(DbUpdateConcurrencyException ex)
{
((IObjectContextAdapter)KnowledgebaseContext).ObjectContext.Refresh(RefreshMode.StoreWins, en);
dbContextTransaction.Rollback();
}
}
我无法在Google或SO上找到这个例外。任何帮助将不胜感激。
答案 0 :(得分:1)
通过查看this和this,我已经能够解决这个问题。有关此功能的文档非常缺乏。
所以这是场景(我们假设已经有一个TimeStamp
列,其值随每次数据库更新而更新):
UserA读取Entity1并开始进行更改。当UserA进行更改时,userB读取Entity1,更改它并将其保存到数据库。现在UserA想要保存她的更改,但现在按照定义,她读取的确切实体不再存在。这样做的原因是该实体的存在也取决于TimeStamp
列,它不再是旧的值。因此当我尝试刷新Entity1时,UserA知道存在,我得到了一个异常,我也无法Refresh
。
现在我们将看一下现有更新实体的并发问题的两种可能解决方案:
Refresh
实体。为了做到这一点,应该在UserA的上下文中覆盖Entity1的TimeStamp
字段,新的字段现在驻留在数据库上,然后尝试从服务器刷新信息。这样,可以在Entity1中找到并检索和填充正确的实体,从而覆盖本地更改。看here寻找另一种方法。TimeStamp
字段,然后再次尝试更新。通过这样做,EF将不再将更新检测为冲突,并且将覆盖服务器上的数据。前面提到的链接也包含这种情况的例子。我不确切地知道为什么在使用Refresh
方法时我得到了异常。我转而使用SetValues
和GetDatabaseValues
等等,我的问题就解决了。