0

我正在尝试创建某种金融系统,我想以高并发模式更新账户余额。当然,我需要独占访问特定帐户记录才能读取实际值并更新它。不幸的是,我无法使用 EF 序列化读取现有记录。问题:是否可以强制 EF 生成更新,例如:

update MyTable
set Balance=Balance+xxx  //where xxx my balance increment
where ID=yyy

代替

update MyTable
set Balance=NewValue
where ID=...

还是我错过了其他一些正确的方法?目前我只看到一种可能的解决方案:使用直接 SQL 命令通过单独的连接更新余额,而不与实体框架交互。

如何重现: 我正在创建 ASP.NET 应用程序,每个线程都有自己的 DbContext 来连接到数据库。我的模型的非常简化的形式如下:

public class Account{
    public int Id {get; set;}
    public decimal Balance {get; set;}
}
public class Entry {
    public int Id {get; set;}
    public int AccountId {get; set;}
    public decimal Amount {get; set;}
}

在发布条目后,我需要更新帐户余额。我正在使用 JMeter 来模拟多用户站点访问。最简单的测试是在几十个线程中发布相同的金额,然后计算所有帐户的总余额。例如,如果我们有 20 个线程,每个线程有 10 个请求,每个线程的 post amount=50,我们应该得到 10000 作为总余额。我知道我需要在这里小心处理数据库锁,并且我知道如何在低级别的数据库访问中执行此操作。我只是想找到一种在没有任何外部东西的情况下使用实体框架的方法。我已经玩TransactionScope了很多,但看起来我不能序列化当前余额值的读取访问。

4

1 回答 1

0

这听起来像实体框架是工作的错误工具。它并不意味着完全取代您与数据库的每一次交互。要按照您说的做,最好的办法是直接运行 SQL。

但是,我建议更改您的数据库结构。您说您将有 200 个(20 个线程 * 10 个请求)更新。为什么不做一个活动表。这 200 次更新将转换为 200 次插入到活动表中。而不是设置Amount = Amount + 50,只需插入50到活动表中。这样就没有任何线程踩到另一个线程的机会。此外,您还可以获得交易的历史记录,如果您需要撤销一笔交易,这非常简单。

编辑

我只是重新阅读了这个问题。看起来你的Entry桌子就是我的建议。在这种情况下,数据库规范化表明您应该Balance从 Account 中删除。当您需要显示它时,即时计算它。

于 2013-08-08T17:52:53.497 回答