Search code examples
databaseentity-frameworkdesign-patternsconcurrencybucket

Working with accumulated bucket values in Entity Framework


I'm attempting to find design patterns/strategies for working with accumulated bucket values in a database where concurrency can be a problem. I don't know the proper search terms to use to find information on the topic.

Here's my use case (I'm using code-first Entity Framework, so EF-specific advice is welcome):

I have a database table that contains a quantity value. This quantity value can be incremented or decremented by multiple clients at the same time (due to this, I call this value a "bucket" value as it is a bucket for a bunch of accumulated activity; this is in opposition of the other strategy where you keep all activity and calculate the value based on the activity). I am looking for strategies on ensuring accuracy of this "bucket" value (within the context of EF) that takes into consideration that multiple clients may attempt to change it simultaneously (concurrency).

The answer "you must track activity and derive your value from that activity" is acceptable, but I want to consider all bucket-centric solutions as well.

I am looking for advice on search terms to use to find good information on this topic as well as specific links.

Edit: You may assume that all activity is relative to the "bucket" value (no clients will be making an absolute change to the value; they will only increment or decrement).


Solution

  • Without directly coding the SQL Queries that update the buckets, you would have to use client-side Optimistic Concurrency. See Entity Framework Optimistic Concurrency Patterns. Clients whose update would overwrite a change will get an exception, after which you can reload with the current value and retry. This pattern requires a ROWVERSION column on the target table.

    If you code the updates in TSQL you can code an atomic update, something like

    update foo with (updlock)
    set bucket_a = bucket_a + 1 
    output inserted.*
    where id = @id
    

    (The 'updlock' isn't strictly necessary in this query, but is good form any time you want to ensure this kind of isolation)