我应该如何处理此实体框架代码中的乐观并发错误?

发布于 2024-08-27 09:45:43 字数 846 浏览 9 评论 0原文

我在一些使用 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(..);
}

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

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

现在,正在发生的情况是:-

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

我不确定这是否类似于竞争条件之类的。

不管怎样,我可以在这里做一些技巧,这样第二次调用就不会崩溃吗?我可以将其放入存储过程..但我希望现在避免这种情况。

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

I have the following pseduo code in some Repository Pattern project that uses 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(..);
}

Pretty simple but I'm getting a run-time error:-

ConcurrencyException: Store, Update,
Insert or Delete statement affected an
unexpected number of rows (0).

Now, this is what is happening :-

  1. Two instances of EF4 are running inthe app at the same time.
  2. Instance A calls delete.
  3. Instance B calls delete a nano second later.
  4. Instance A loads the entity.
  5. Instance B also loads the entity.
  6. Instance A now deletes that entity - cool bananas.
  7. Instance B tries to delete the entity, but it's already gone. As such, the no-count or what not is 0, when it expected 1 .. or something like that. Basically, it figured out that the item it is suppose to delete, didn't delete (because it happened a split sec ago).

I'm not sure if this is like a race-condition or something.

Anyways, is there any tricks I can do here so the 2nd call doesn't crash? I could make it into a stored procedure.. but I'm hoping to avoid that right now.

Any ideas? I'm wondering If it's possible to lock that row (and that row only) when the select is called ... forcing Instance B to wait until the row lock has been relased. By that time, the row is deleted, so when Instance B does it's select, the data is not there .. so it will never delete.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

趴在窗边数星星i 2024-09-03 09:45:43

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

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

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

Normally you would catch the OptimisticConcurrencyException and then handle the problem in a manner that makes sense for your business model - then call SaveChanges again.

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

Give that a whirl and see how you get on - not tested/compiled or anything - I've used DeletingObject as the type of the entity you're trying to delete. Substitute for your entity type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文