我正在尝试创建某种金融系统,我想在高并发模式下更新帐户余额。当然,我需要对特定帐户记录进行独占访问才能读取实际值并进行更新。不幸的是,我无法使用EF序列化现有记录的读取。 问题:是否可以强制EF生成以下更新:
update MyTable
set Balance=Balance+xxx //where xxx my balance increment
where ID=yyy
而不是
update MyTable
set Balance=NewValue
where ID=...
或者我错过了其他一些正确的方法?目前我只看到一种可能的解决方案:使用直接SQL命令通过单独连接更新平衡,而无需与Entity Framework交互。
如何重现: 我正在创建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个请求,每个帖子的数量= 50,我们应该得到10000作为总余额。
我知道我需要在这里仔细处理数据库锁,我知道如何在低级别的数据库访问中执行此操作。我只是想找到一种方法来使用Entity Framework而不需要任何外部的东西。我已经玩了很多TransactionScope
,但看起来我可以;序列化当前余额值的读取权限。
答案 0 :(得分:0)
这听起来像Entity Framework是错误的工具。它并不是要完全取代您与数据库的每次互动。要做到你说的话,最好的办法就是直接运行SQL。
但是,我建议您更改数据库结构。您声明您将有200(20个线程* 10个请求)更新。为什么不制作活动表。这200个更新将转换为活动表中的200个插入。不要设置Amount = Amount + 50
,只需将50
插入活动表即可。这样就不会有任何线程踩到另一个线程。此外,您还可以获得交易历史记录,如果您需要退出交易,那么这很简单。
修改强>
我刚刚重新阅读了这个问题。看起来你的Entry
表就是我的建议。在这种情况下,数据库规范化表明您应该从帐户中删除Balance
。需要显示时,请动态计算。