c# - 更新并发事务 C# 的数量问题

标签 c# asp.net entity-framework concurrency transactions

我开发了一个在线购买我的产品的应用程序。 我的商店里有一个产品“雨伞”,有 100 件。我开发了一个在线购买我的产品的应用程序。 但是当有并发购买时会出现问题。

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

当有两个单独的事务时,这将正常工作。但当这两笔交易同时发生时,这是一个问题。这个问题的原因是,当并发事务检查可用性的条件同时命中时,由于数据库表没有更新最新的数量,此时条件被满足。

我该如何纠正这个问题?

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;
            }
        }
    }
}

只有一个线程可以获得在_availableQtyLock上获得锁的独占权,这意味着其他线程将不得不等待第一个线程释放对该对象的锁。

考虑到这是处理并发的最简单(也可能是最慢)的方法,还有其他方法可以进行线程同步,例如MonitorSemaphore、快速 SlimLock 等...因为很难说出哪一个最适合您的需求,您需要进行适当的性能/压力测试,但我的建议是从最简单的开始。

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

关于c# - 更新并发事务 C# 的数量问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53185716/

相关文章:

c# - 指定的 key 太长;最大 key 长度为 767 字节 Entity Framework 6 中的 Mysql 错误

c# - 将JSON数据反序列化为C#中的任何类型

c# - 字符串是否存在检查 20k 次

c# - 如何列出 MVC 用户及其角色?

c# - 从我的类(class)访问母版页/子页控件

entity-framework - 返回空的 IQueryable<>

c# - 返回派生类实例的抽象方法

c# - 非常频繁地更新datagridview

javascript - 将 ArrayList 转换为 JavaScript 表

c# - HasColumnType 和数据库生成的正确用法是什么