2016-08-22 13 views
5

Mam następujące metody dodawania lub aktualizowania obiektu typu Item dla niektórych użytkowników. Ta metoda jest częścią klasy serwisowej, której nowe wystąpienie jest tworzone dla każdego żądania.ASP.NET Web API - logika wątku w celu aktualizacji jednostki

public async Task SaveItem(int userId, string name) 
{ 
    var item = await _context.Items.Where(i => i.UserId == userId).SingleOrDefaultAsync(); 

    if (item == null) 
    { 
     item = new Item 
     { 
      UserId = userId, 
      Name = name 
     }; 
     _context.Items.Add(item); 
    } 
    else 
    { 
     item.Name = name; 
     _context.Entry(item).State = System.Data.Entity.EntityState.Modified; 
    } 

    await _context.SaveChangesAsync(); 
} 

Problem polega na tym, że dwie jednoczesne żądania mogą utworzyć dwie pozycje dla tego samego użytkownika, które nie są prawidłowe. Wydaje mi się, że jest to całkiem popularny kod i zastanawiam się, jaki jest domyślny sposób radzenia sobie z tego rodzaju problemem współbieżności.

Odpowiedz

2

Musisz poprawnie obsługiwać Concurrency Conflicts w swojej aplikacji.

1.Pessimistic współbieżności (blokowanie)

Jeśli aplikacja wymaga, aby zapobiec przypadkowej utracie danych w scenariuszy współbieżności, jednym ze sposobów, aby to zrobić jest użycie blokady bazy danych. To się nazywa pesymistyczna współbieżność. Na przykład przed przeczytaniem wiersza z bazy danych zażądano blokady dostępu tylko do odczytu lub aktualizacji . Jeśli zablokujesz wiersz w celu uzyskania dostępu do aktualizacji, żaden inny użytkownik nie może zablokować wiersza w trybie tylko do odczytu lub aktualizacji, ponieważ otrzyma kopię danych, które są w trakcie zmiany. Po zablokowaniu wiersza w trybie tylko do odczytu inni mogą również zablokować go w celu uzyskania dostępu tylko do odczytu, ale nie w celu aktualizacji.

2.Optimistic współbieżności

Alternatywą dla współbieżności pesymistycznym jest optymistyczna współbieżność. Optymistyczna współbieżność oznacza możliwość wystąpienia konfliktów współbieżnych, , a następnie odpowiednia reakcja, jeśli tak się stanie.

Przeczytaj artykuł Handling Concurrency with the Entity Framework, aby uzyskać więcej informacji.

+1

Dzięki, to było pomocne łącze. Zakończyłem wdrażanie optymalnej obsługi za pomocą try/catch. –

+0

Tak, bardzo dobrze. Chciałbym Ci pomóc :) – Sampath

1

Jeśli kombinacja UserId i Name dla elementu ma być unikalna, należy uczynić go unikalnym w bazie danych.

Możesz spróbować rozwiązać ten problem za pomocą statycznych obiektów blokujących ... ale to tylko sprawi, że będzie wolne i trudne do zrozumienia/utrzymania.

0

Możesz mieć dwie oddzielne funkcje, jedną, która tworzy i jedną aktualizującą. Lub możesz spróbować zaktualizować, a jeśli się nie powiedzie, utwórz go i nie zapomnij umieścić unikalnego indeksu w bazie danych.

0

Jeśli pole jest oznaczone jako unikatowe (lub tożsamość, która jest również unikalna), oznacza to, że już wszystko jest w porządku. Za każdym razem, gdy dostajesz się do tej niewielkiej luki czasowej, aby dodać więcej niż jeden produkt z tym samym UserId, tylko pierwszy zakończy się sukcesem, a wszystkie inne nie powiedzie się podczas dodawania.