【发布时间】:2018-10-21 08:52:30
【问题描述】:
我正在为我的 ASP.Net 网站使用 Entity Framework 6.0 和 SQL Server 2016。我最近在我的一个函数中发现了并发问题。该函数用于处理未付款的订单,有时该函数会针对同一个key、同一时间执行多次(因为多个用户同时访问)。
这是它的样子。
public void PaidOrder(string paymentCode)
{
using (MyEntities db = new MyEntities())
{
using (DbContextTransaction trans = db.Database.BeginTransaction())
{
try
{
Order_Payment_Code payment = db.Order_Payment_Code.Where(item => item.PaymentCode == paymentCode).FirstOrDefault();
if(payment.Status == PaymentStatus.NotPaid)
{
//This Scope can be executed multiple times
payment.Status = PaymentStatus.Paid;
db.Entry(payment).State = EntityState.Modified;
db.SaveChanges();
//Continue processing Order
trans.Commit();
}
}
catch (Exception ex)
{
trans.Rollback();
}
}
}
}
我不明白的是,为什么我的if 语句中的范围即使在事务中也可以多次执行?事务不是应该隔离数据吗?还是我对交易的理解有误?如果是这样,那么让我的 if 语句中的范围只执行一次的正确方法是什么?
【问题讨论】:
-
取决于几件事:事务的隔离级别(默认为 ReadCommitted),以及您在该事务中执行的操作。
-
@MitchWheat 我没有设置任何隔离级别选项,所以我认为这是默认设置。除了更新上面的
PaymentStatus之外,我所做的基本上是插入和更新其他一些表。 -
你真正的问题在这里“有时这个函数会在同一个键和同一时间执行多次(因为多个用户一起访问它)。”与其锁定表并阻止所有其他访问,不如解决原因而不是症状。
-
@MitchWheat,我认为这不可能,因为连接到此功能的页面显示未付款订单列表和一个将付款状态设置为已付款的按钮。我无法阻止该按钮仅单击一次,因为该页面由多个用户访问。所以我试图阻止使用事务的表(至少即使多次单击该按钮,它也只在第一次单击时处理一次)。但不幸的是,它没有按预期运行。
-
至少你应该实现乐观并发。
标签: c# sql-server entity-framework transactions