2

我在一些使用EF4的存储库模式项目中有以下伪代码。

public void Delete(int someId)
{
   // 1. Load the entity for that Id. If there is none, then null.
   // 2. If entity != null, then DeleteObject(..);
}

很简单,但我遇到了运行时错误:-

ConcurrencyException:存储、更新、插入或删除语句影响了意外的行数 (0)。

现在,这就是正在发生的事情:-

  1. EF4 的两个实例同时在应用程序中运行。
  2. 实例 A 调用删除。
  3. 实例 B 在一纳秒后调用 delete。
  4. 实例 A 加载实体。
  5. 实例 B 还加载实体。
  6. 实例 A 现在删除了该实体 - 酷香蕉。
  7. 实例 B 尝试删除实体,但它已经消失了。因此,当它期望 1 .. 或类似的东西时,无计数或什么不是 0。基本上,它发现它应该删除的项目没有删除(因为它发生在几秒钟前)。

我不确定这是否像比赛条件或其他东西。

无论如何,我可以在这里做些什么让第二次通话不会崩溃?我可以把它变成一个存储过程..但我希望现在避免这种情况。

有任何想法吗?我想知道是否可以在调用 select 时锁定该行(并且仅该行)......强制实例 B 等待行锁被释放。到那时,该行已被删除,因此当实例 B 选择时,数据不存在.. 所以它永远不会删除。

4

1 回答 1

0

通常,您会捕获 OptimisticConcurrencyException,然后以对您的业务模型有意义的方式处理问题 - 然后再次调用 SaveChanges。

try
{
    myContext.SaveChanges();
}
catch (OptimisticConcurrencyException e)
{
    if (e.StateEntries.FirstOrDefault() is DeletingObject)
        myContext.Detach(e.StateEntries.First();
    myContext.SaveChanges();
}

试一试,看看你是如何开始的 - 没有经过测试/编译或任何东西 - 我使用 DeletingObject 作为你要删除的实体的类型。替换您的实体类型。

于 2010-05-14T12:25:47.693 回答