concurrency and atomicity Asp.net core web api and efcore

let's say there's an endpoint called AssingUser() ,this endpoint assigns one donation to this current user who requested it, the idea is that , in the mobile application front end, the view of assignment is shared between many users , so let's say two users clicked at the same time to be assigned to this current donation, how can i make sure that one and only one is able to be set at this same time ? I'm not sure if i delivered what i want clearly πŸ˜…
20 Replies
Pobiega
Pobiegaβ€’12mo ago
There are a ton of solutions to this, naturally. The simplest way is to just query the object status before doing the actual assigning, thus checking that the status is still available
Esa
Esaβ€’12mo ago
Some databases support this select * from X where Y for update. What that does is return a result that is locked on a row-level, meaning that returned result cannot be changed by other transactions. This should equate to an optimistic locking, which I think is sufficient for your usecase. The big benefit to this is that it happens in the same transaction as you fetch the entry, meaning you don't need two roundtrips to a) get the entry b) update its status, because it will be locked by that point.
▬▬ι═══════ﺀ
yeah but can't the two requests be reading the same record at the same time ? or is the record automatically locked when some other transaction or query is reading it? looks nice , im using efcore with Sql server , any idea how to use this facility ?
Pobiega
Pobiegaβ€’12mo ago
Sure, and there are ways to solve that. Row locking on the database, or using something like Redis to acquire a shared lock, etc It all depends on what you are using and how your application is structured and scaled
▬▬ι═══════ﺀ
let me clarify my concerns : let's say the logic is like that : - request comes - check if there's a user assigned to this donation - if not, assign this current user(update the record ) - if it's already assigned, return bad request ----------- my concerns are : both requests read that record and it isn't assigned yet, both will want to update this record
Pobiega
Pobiegaβ€’12mo ago
No I understand. The timing window for that is very small but its possible. And if that 100% must not be allowed, there are many ways to solve it. I suggested a few above. Another one is with an E-tag, a column on the database where each row has some randomly generated value when you fetch it, you read the e-tag. you then include the e-tag in your update statement
UPDATE TABLENAME SET X = y, etag = 'newuniquevalue' WHERE Id = 12312451 AND etag = 'uniquevaluefrombefore';
UPDATE TABLENAME SET X = y, etag = 'newuniquevalue' WHERE Id = 12312451 AND etag = 'uniquevaluefrombefore';
if the update fails, the etag has changed and you need to re-check if you still can access it
▬▬ι═══════ﺀ
wait I'll try to understand this πŸ˜…
Pobiega
Pobiegaβ€’12mo ago
the only way to get the e-tag is to read it from the database. any edit to the row also updates the e-tag πŸ™‚ this is how document databases deal with this scenario, usually
▬▬ι═══════ﺀ
aaah ,like a unique stamp for like "who read this record"
Pobiega
Pobiegaβ€’12mo ago
sure
▬▬ι═══════ﺀ
cool idea Alright thank you pobiega anyone interested on how i (not me efcore did) solved this problem ?
Pobiega
Pobiegaβ€’12mo ago
sure
Pobiega
Pobiegaβ€’12mo ago
Ah, its essentially an e-tag
Pobiega
Pobiegaβ€’12mo ago
if combined with .ValueGeneratedOnAddOrUpdate() its even automated. nice.
▬▬ι═══════ﺀ
but i was shocked how easy to implement it yeee in my case i don't want it to generat a value when reading or when writing so i just used IsConcurrencyToken

Did you find this page helpful?