We have a MVC Web API that is called to write transactions for a specific amount, where the amount is debited or credited to a user's balance. This records the balance pre-transaction (PreAmount), the amount, and the balance post-transaction (PostAmount). We noticed from a simple query using SQL Server's LAG
and LEAD
functions that there were instances of transactions being added from the API were being 'entered too fast' (partially due to the lack of resources put towards buying good hardware for the server, and IIS and SQL running on the same box). We have a mechanism to prevent the transaction from being entered if it exists, but it seems that the method call is being called really quickly, which results in the record being added multiple times due to a race condition.
The way I am going to try to fix this is by using a Dictionary<long, object>
. The assumption here is that, we want transactions for a customer to be entered sequentially at all times, but I don't want to lock concurrent requests for multiple customers. The dictionary would contain a customer ID # and the value would be an object I can lock on. When a transaction is about to be entered, I will check to see if there is a customer ID # entry, and if not, enter it in there):
private static Dictionary<long, object> customerLocker = new Dictionary<long, object>();
private static object dictLocker = new object();
Then, when a request to check a balance, or to enter a transaction is requested, I would then lock on that object, and perform the work needed:
lock (dictLocker)
{
if (!customerLocker.ContainsKey(customerID))
customerLocker.Add(customerID, new object());
}
lock (customerLocker[customerID])
{
// ... do the work needed for this customer
}
Is this a good solution to the issue I am having? Will locking on elements inside of a dictionary cause issues? I'm going to try it, but while I'm putting this together, I'd like to see input from others on this scenario.