我正在一个网站上工作,我在其中使用Asp.Net MVC和Entity Framework 6.每个用户都有一个信用卡,有时用户可以将信用转移给其他用户。简单的方法是:
public class ApplicationUser : IdentityUser
{
//....
public decimal Credit { get; set; }
}
var user1 = await db.Users.FindAsync(id1);
var user2 = await db.Users.FindAsync(id2);
user1.Credit -= amount;
user2.Credit += amount;
await db.SaveChangesAsync();
但是,我认为这很容易受到并发问题的影响。例如,如果两个用户在同一时间转移给用户会怎么样?
由于我们将在网站上使用真钱作为信用,因此解决此问题的最安全和防故障方法是什么?
答案 0 :(得分:1)
答案 1 :(得分:1)
默认情况下,EntityFramework会将<?php and ?>
包装到事务中。所以你的改变要么成功要么一起失败。
你能做什么:
您可以将代码明确地包装到TransactionScope()
中使用(TransactionScope scope = new TransactionScope()) { //需要在事务中以原子方式工作的代码 }
或者
这是银行的做法。每当交易发生时,将账户和信用卡的借记存储到另一个账户。
然后,当您查询用户的余额时,您将根据所有事务的总和来聚合最终余额(对于任何支持SQL的DBMS都非常容易)
答案 2 :(得分:0)
建议:
让您的流程首先从旧帐户中删除资金,然后确认交易已过帐到旧帐户,然后将资金应用到新帐户。
在每次转移时记录序列号,并确认何时向其帐户发布该交易具有该交易的正确序列号。这只是一个很好的做法,因此您可以记录每次转移。
将债务过账到源帐户后,确认帐户余额不是负数。如果是,请取消交易。这可以防止对现有余额进行多次借记,然后在每次债务应用于源帐户后(最终增加的安全措施)结果为负数。另外,确保转移的金额是正数。一个简单的黑客骗局是从其他人的帐户转移负数(因此增加了黑客的帐户)。
如果您不信任您使用的框架,有许多方法可以手动执行此操作,并且应该进行许多检查以降低欺诈风险。
您可以锁定两个记录,进行转移,然后解锁两个记录。锁定前,确保它们尚未锁定。这样,两个记录都会被锁定,直到事务完成。
没有什么能取代对交易日志的需求,恕我直言。