s.k.paul
s.k.paul

Reputation: 7291

Using lock in Hangfire executed ASP.Net code

I am using hangfire in an ASP.Net MVC project to manage longrunning background job.

I am trying to use lock statement block for database operation. Here is my lock statement code-

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

Here is how I'm calling the above code-

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

The problem is, database value is not updated as expected. For example, I have 5 queues as follows -

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;

Database value should be deducted 2.5 (cost total) after completing the loop. But it's not happening. Sometimes deducted value is 2.00, sometimes 1.5, etc.

Any suggestion?

Upvotes: 2

Views: 1431

Answers (1)

Set
Set

Reputation: 49779

Your lock object (thisLock) is an instance property. And cause in foreach loop you create a new instance of LockedTransaction for each element in the queue, lock doesn't prevent concurrent executions (each calling of UpdateCustomerBalance method uses own lock object).

Changing thisLock to static property should help you:

private static Object thisLock = new Object();

Upvotes: 1

Related Questions