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

时间:2018-02-02 07:03:33

标签: sql-server asp.net-mvc hangfire

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

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

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,等等。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

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

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

private static Object thisLock = new Object();