使用并发事务更新数量问题C#

使用并发事务更新数量问题C#,c#,asp.net,entity-framework,concurrency,transactions,C#,Asp.net,Entity Framework,Concurrency,Transactions,我开发了一个在线购买产品的应用程序。 我的店里有一款产品“雨伞”,有100件。我开发了一个在线购买产品的应用程序。 但同时进行采购时会出现一个问题 如果同时发生两次采购,可用数量将不正确更新。假设有两个交易同时发生,采购数量为100和50。理想情况下,第一笔交易(采购数量为100)应该是成功的,因为我们有100个库存。但是第二笔交易应该返回一个错误,因为股票不足以处理第一笔交易,余额为0。(100 - 100). 但是在上面的场景中,两次交易都成功了,余额现在显示为-50 当存在两个单独的事务时

我开发了一个在线购买产品的应用程序。 我的店里有一款产品“雨伞”,有100件。我开发了一个在线购买产品的应用程序。 但同时进行采购时会出现一个问题

如果同时发生两次采购,可用数量将不正确更新。假设有两个交易同时发生,采购数量为100和50。理想情况下,第一笔交易(采购数量为100)应该是成功的,因为我们有100个库存。但是第二笔交易应该返回一个错误,因为股票不足以处理第一笔交易,余额为0。(100 - 100). 但是在上面的场景中,两次交易都成功了,余额现在显示为-50

当存在两个单独的事务时,这将正常工作。但当这两项交易同时发生时,这是一个问题。此问题的原因是,当并发事务同时达到检查可用性的条件时,由于DB表未使用最新数量更新,因此在此期间满足该条件

我怎样才能纠正这个问题

public bool UpdateStock(int productId, int purchaseQty)
{
    using(var db = new MyEntities())
    {
       var stock = db.Products.Find(productId);

       if (stock.AvailableQty >= purchaseQty) // Condition to check the availablity
       {
            stock.AvailableQty = stock.AvailableQty - purchaseQty;
            db.SaveChanges();
            return true;
        }
        else
        {
            return false;
        }
    }
}

这是典型的线程并发问题,可以通过多种方式解决,其中之一是使用简单的
lock
语句:

public class StockService
{
    private readonly object _availableQtyLock = new object();

    public bool UpdateStock(int productId, int purchaseQty)
    {
        using (var db = new MyEntities())
        { 
            lock (_availableQtyLock)
            {
                var stock = db.Products.Find(productId);
                if (stock.AvailableQty >= purchaseQty) // Condition to check the availablity
                {
                    stock.AvailableQty = stock.AvailableQty - purchaseQty;
                    db.SaveChanges();
                    return true;
                }
                return false;
            }
        }
    }
}
只有一个线程可以获得独占权限以获得对
\u availableQtyLock
的锁定,这意味着其他线程必须等待第一个线程释放对该对象的锁定

考虑到这是处理并发性的最简单(可能也是最慢)的方法,还有其他方法来进行线程同步,例如,
监视器
信号灯
,fast
SlimLock
等。。。因为很难判断哪一个最适合您的需求,所以您需要进行适当的性能/压力测试,但我的建议是从最简单的测试开始


注意:正如其他人在评论中提到的,并发问题也可以在DB级别上解决,这确实更合适,但如果您不想/不能引入任何DB更改,这将是一种方法

查找乐观并发和实体framework@TheGeneral或者悲观并发(锁定行)。a) 根据@TheGeneral的评论()的乐观并发性。b) 使用直接SQL,如
updatetable SET AvailableQty=AvailableQty-@purchaseQty,其中AvailableQty>=@purchaseQty
,然后检查更新后的行数。hrm,这似乎不太可伸缩我完全同意,然而,在这种情况下,可伸缩性不是必需的,对吗?如果我们有100个库存,两个并发事务是针对数量50和30的呢?那么我应该将余额视为20?@Duminda是的,这是正确的,因为第一个线程(或事务)将保存更改(即将数量减去50),然后第二个线程将从DB获得产品,该产品的数量为50,然后将其减去30:)希望没有多个此类
StockService
。或者一个网络花园。或者一个网络农场。当数据库内置了并发处理时,这似乎是一个奇怪的解决方案。