在 Hangfire 中使用锁执行 ASP.Net 代码

Using lock in Hangfire executed ASP.Net code

我在 ASP.Net MVC 项目中使用 hangfire 来管理长时间运行的后台作业。

我正在尝试使用锁定语句块进行数据库操作。这是我的锁定语句代码-

public class LockedTransaction
{
    private Object thisLock = new Object();

    public LockedTransaction() { }

    public void UpdateCustomerBalance(long CustomerId, decimal AmountToDeduct, string ConnectionString)
    {
        lock (thisLock)
        {
            using (SqlConnection connection = new SqlConnection(ConnectionString))
            {
                connection.Open();
                using (SqlTransaction transaction = connection.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)) 
                {
                    using (SqlCommand command = new SqlCommand())
                    {
                        command.Connection = connection;
                        command.Transaction = transaction;

                        command.CommandText = "SELECT Balance FROM Customer WHERE Id=" + CustomerId;
                        var userBalance = Convert.ToDecimal(command.ExecuteScalar());
                        userBalance = userBalance - AmountToDeduct;

                        command.CommandText = "UPDATE Customer SET Balance=" + userBalance + "  WHERE Id=" + CustomerId;

                        command.ExecuteNonQuery();
                        transaction.Commit();
                    }
                }
            }
        }
    }
}

下面是我如何调用上面的代码-

foreach (var queue in queues)
{
     queue.Send();
     LockedTransaction lockedTransaction = new LockedTransaction();
     lockedTransaction.UpdateCustomerBalance(queue.CustomerId, queue.cost, "ConnectionString");
}

问题是,数据库值没有按预期更新。比如我有5个队列如下-

queue[0].cost = 0.50;
queue[1].cost = 0.50;
queue[2].cost = 0.50;
queue[3].cost = 0.50;
queue[4].cost = 0.50;

循环完成后,数据库值应扣除2.5(总成本)。但它没有发生。有时扣除值是2.00,有时是1.5,等等

有什么建议吗?

您的锁定对象 (thisLock) 是一个实例 属性。在 foreach 循环中,您为队列中的每个元素创建了一个 LockedTransaction 的新实例,lock 不会阻止并发执行(每次调用 UpdateCustomerBalance 方法都使用自己的锁对象)。

thisLock 更改为静态 属性 应该可以帮助您:

private static Object thisLock = new Object();