DbContext,处理并发异常

时间:2012-12-13 11:09:28

标签: entity-framework dbcontext optimistic-concurrency

使用EF DbContext。我的实体对象有rowversion列(SQL Compact版本4),用于并发检查(ConcurrencyMode = Fixed,StoreGeneratedPattern = Computed)。

为了强制并发异常,我从UI中以2种不同的形式读取相同的表记录,编辑每个表,然后一个接一个地保存。以下代码执行实际的保存操作。

单击第二个表单上的保存按钮时,会出现预期的并发错误。然而, 从数据库复制原始值后,异常仍然在第二次尝试时仍然存在。只有第三次尝试成功,没有任何错误。有人可以解释一下可能导致这个问题的原因吗?

try
{
  _ctx.SaveChanges(); //first attempt
}
catch (Exception ex)
{
  if (ex is DbUpdateConcurrencyException)
  {
    var exc = ex as DbUpdateConcurrencyException;
    foreach (var entry in exc.Entries)
      entry.OriginalValues.SetValues(entry.GetDatabaseValues());
    try
    {
      _ctx.SaveChanges(); //second attempt
    }
    catch (Exception ex2)
    {
      if (ex2 is DbUpdateConcurrencyException)
      {
        var exc2 = ex2 as DbUpdateConcurrencyException;
        foreach (var entry in exc2.Entries)
          entry.OriginalValues.SetValues(entry.GetDatabaseValues());
        try
        {
          _ctx.SaveChanges(); //third attempt
        }
        catch (Exception ex3)
        {
          System.Windows.MessageBox.Show(ex3.Message);
        }
      }
    }
  }
}

编辑:我发现当我通过UI进行两次更新时都会发生这种情况。如果在上面的代码中,在第一次尝试之前,我会执行以下操作:

var _ctx2 = new MyDbContext();
var myEntity = _ctx2.MyEntities.Where(ent => ent.Id == 2).Single();
myEntity.Name = "My new name";
_ctx2.SaveChanges();
_ctx2.Dispose();

然后代码按预期工作,因为myEntity的另一个实例是通过UI更新的;即第二次尝试将拯救myEntity。 而且,问题在于以下几行:

foreach (var entry in exc.Entries)
  entry.OriginalValues.SetValues(entry.GetDatabaseValues());

因为,当通过UI更新时,exc.Entries不返回发生并发错误的实体,而是返回其导航属性实体。

在这种情况下,MyEntity是一个类似树的自引用实体,它有两个导航属性:ParentEntity和Children。

因此,在第一次保存尝试之后,我在exc.Entries中拥有的是ParentEntity(处于未更改状态),并且仅在第二次保存尝试之后,exc.Entries返回引发并发错误的实际实体。

1 个答案:

答案 0 :(得分:1)

好吧,这似乎是一个EF错误。请参阅以下内容:

http://support.microsoft.com/kb/2390624#appliesto
http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/ce60bf40-cd05-42f6-ab8f-26b048ec83d7
相关问题