2

设想:

我有多个帐户。每个帐户都有剩余信用。每个帐户对应多个用户。

我希望 RemainingCredit 字段正确反映剩余信用(我正在使用 EF 抽象出数据库)。

EG在初始信用为X且 2 个用户登录的情况下,一个花费A,一个花费B,我希望最终总和为XAB(读取/修改/保存的顺序应该无关紧要)。

阅读后,我认为乐观并发处理是我正在寻找的,因为它可以很好地扩展,这对我的场景非常重要。最终过程将类似于:

ComputeRemainingCredit(Double amountToBeDeducted) {
    Account acc = context.Accounts.Where(condition)
    ComputeRemainingCreditInternal(acc, amountToBeDeducted);
}

ComputeRemainingCreditInternal(Account acc, Double amountToBeDeducted) {
try {
    acc.RemainingCredit = acc.RemainingCredit - amountToBeDeducted;
    context.SaveChanges();
}
catch (OptimisticConcurrencyException  ex) {
    context.Refresh(RefreshMode.StoreWinds, acc);
    //now I need to rerun the operation
    ComputeRemainingCreditInternal(acc, amountToBeDeducted);
}
}
  1. 这是 EF 中乐观并发的正确解释/实现吗?
  2. 我的最终目标是更新 RemainingCredit 字段。有没有比 OptimisticConcurrencyException 更好的解决方案?
4

2 回答 2

2

您需要在表中充当时间戳或版本号的字段,并将其用于乐观并发检查。

假设你有一个Version字段。将该字段的ConcurrencyMode属性设置为Fixed,然后 EF 将为您进行乐观并发检查并OptimisticConcurrencyException在必要时抛出一个。

另一种方法是自己完成这项工作——获取当前记录,根据您正在更新的记录中的字段值验证字段值,相应地允许或禁止更新。

编辑另见http://blogs.msdn.com/b/alexj/archive/2009/05/20/tip-19-how-to-use-optimistic-concurrency-in-the-entity-framework.aspx

在伪代码中或多或少地编辑:

bool mustRetry = true;
while (mustRetry)
{
    try
    {
        SpendTheMoney(context, parameters);
        mustRetry = false;
    } catch (OptimisticConcurrencyException exc)
    {
        // Do logging if you need, then just swallow the exception
    }
}
于 2012-12-10T13:50:14.837 回答
0

作为替代方案,您可以向用户显示一条错误消息,说明操作失败,因为数据已被修改,然后向他显示数据的当前状态。如果这是他/她的意图,那么用户将决定重试该操作。

你可以在这里找到一篇关于实体框架中并发的好文章:

在 ASP.NET MVC 应用程序中使用实体框架处理并发

于 2012-12-10T14:11:57.237 回答