Wpis z mikrobloga

Ej mireczki mam taką rozkmine jak ludzie implementują niektóre rzeczy w .NET Core + Ef Core. Załóżmy taki scenariusz, że robimy sobie sklep internetowy i mamy klasę Product.cs w której jest zdefiniowana propertka Amount. W sytuacji gdy ktoś składa zamówienie (czyli strzela do endpointa) to na danym produkcie zmniejszamy Amount o odpowiednią liczbę.

Jak to rozwiązać, żeby to było w 100% bezpieczne i nie pojawiła się sytuacja, gdy dwie osoby zrobią dokładnie w tym samym momencie zamówienie na ten sam produkt i będą miały tą samą wartość Amount i każda z nich zmniejszy bazą wartość Amount i to zapisze 'tylko po jednej zmianie' :

1. var product = await _context.Products.FirstOrDefault(x => x.Id == request.productId);
2. product.Amount -= request.amount;
//tutaj jakaś długa operacja załóżmy
3. await _context.SaveChangesAsync()

I teraz załóżmy Klient1 jest pomiędzy 2., a 3. i wskakuje Klient2 i robi 1. przez co ma jeszcze starą wartość w product.

Czy tutaj powinniśmy użyć jakichś Mutexów? A może struktura bazy jest głupia i nie powinniśmy w taki sposób przechowywać "Amount"?

#csharp #netcore #programowanie #programista15k #webdev
  • 15
@waniliowe-ptasie-mleczko: Wg mnie baza musi trzymać timestamp/row version dla rekordu i wtedy w ef można ręcznie rozstrzygnąć co ma zrobić aplikacja np. pobrać obiekt ponownie i powtórzyć operację. Można tego uniknąć stosując event sourcing ale trzeba się wtedy pogodzić z tym że np. możemy czasami zejść poniżej 0 jeśli nie zastosujemy dodatkowych technik.
@Whiskeyjack29: zmyliło mnie to że w tym krótkim tutorialu nie ma modelu i założyłem że EF robi to jakoś automatycznie. Po przejrzeniu na szybko innych źródeł wygląda na to że do takich sztuczek EF musi mieć rowversion lub krytyczne property musi być dodatkowo skonfigurowane żeby EF je sprawdził - masz rację co do tego. Co do rozwiązywania wykrytego problemu - to już zależy od wymagań, w tym tutorialu są dwa podstawowe
użyj jakiegoś concurrency token, żadne semafory ani locki nie pomogą, jeżeli będziesz mieć więcej niż jedną instancję aplikacji.


@kotwica407: Optimistic locking to właśnie inna nazwa na concurrency tokeny