实体框架乐观并发异常处理

时间:2015-04-20 17:54:34

标签: c# entity-framework

我试图解决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上找到这个例外。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

通过查看thisthis,我已经能够解决这个问题。有关此功能的文档非常缺乏。

所以这是场景(我们假设已经有一个TimeStamp列,其值随每次数据库更新而更新):

UserA读取Entity1并开始进行更改。当UserA进行更改时,userB读取Entity1,更改它并将其保存到数据库。现在UserA想要保存她的更改,但现在按照定义,她读取的确切实体不再存在。这样做的原因是该实体的存在也取决于TimeStamp列,它不再是旧的值。因此当我尝试刷新Entity1时,UserA知道存在,我得到了一个异常,我也无法Refresh

现在我们将看一下现有更新实体的并发问题的两种可能解决方案:

  • 忽略UserA的更改(存储获胜):这基本上意味着将从数据库中Refresh实体。为了做到这一点,应该在UserA的上下文中覆盖Entity1的TimeStamp字段,新的字段现在驻留在数据库上,然后尝试从服务器刷新信息。这样,可以在Entity1中找到并检索和填充正确的实体,从而覆盖本地更改。看here寻找另一种方法。
  • 覆盖数据库上的更改(客户端获胜):在这里,我们将覆盖TimeStamp字段,然后再次尝试更新。通过这样做,EF将不再将更新检测为冲突,并且将覆盖服务器上的数据。前面提到的链接也包含这种情况的例子。

我不确切地知道为什么在使用Refresh方法时我得到了异常。我转而使用SetValuesGetDatabaseValues等等,我的问题就解决了。