Autorwww.itsvse.com @小渣渣 ! Wprowadź dane bazowe pomyślnie! Testowanie funkcji Concurrency Check zakończone Aktualizacja zakończona! Przypis 1 Aktualizacja jest wyjątkowa! Uwaga 2, nienormalne informacje! Instrukcje aktualizacja, wstawienie lub usunięcie zapisu dotyczyły nieoczekiwanej liczby wierszy (0). Podmioty mogły zostać zmodyfikowane lub usunięte od czasu załadowania. Zobacz http://go.microsoft.com/fwlink/?LinkId=472540, aby uzyskać informacje o rozumieniu i radzeniu sobie z optymistycznymi wyjątkami współbieżności.
Sprawdź różnicę między Timestamp a Concurrency Check Aktualizacja Tab1 zakończyła się sukcesem! Nazwa 1 Aktualizacja Tab2 zakończyła się sukcesem! Nazwa 1 Aktualizacja Tab2 jest nietypowa! Nazwisko 2, nietypowe informacje! Instrukcje aktualizacja, wstawienie lub usunięcie zapisu dotyczyły nieoczekiwanej liczby wierszy (0). Podmioty mogły zostać zmodyfikowane lub usunięte od czasu załadowania. Zobacz http://go.microsoft.com/fwlink/?LinkId=472540, aby uzyskać informacje o rozumieniu i radzeniu sobie z optymistycznymi wyjątkami współbieżności. Aktualizacja Tab1 zakończyła się sukcesem! Nazwa 2
【TimeStamp】 Funkcję TimeStamp można zastosować do klasy pola, która ma tylko jedną właściwość tablicy bajtowej, a ta funkcja przypisuje typ tiemStamp do kolumny. W kontrolach równoległych Code-First automatycznie używa tego pola typu TimeStamp.
【ConcurrencyCheck】 Funkcję ConcurrencyCheck można zastosować do właściwości klasy domeny. Gdy EF wykonuje operację aktualizacji, Code-First umieszcza wartość kolumny w instrukcji where-condition, a funkcja CurrencyCheck pozwala wykorzystać istniejące kolumny do sprawdzania współbieżności, zamiast używać osobnej kolumny TimeStamp do sprawdzania współbieżności.
Zacznijmy od stworzenia nowego obiektu kontekstowego, który pokaże różnicę między Timestamp a Concurrency Check w przetwarzaniu współbieżności!
Oto kod do kontekstu:
Przyjrzyjmy się kolumnom bazy danych, w następujący sposób:
Okazuje się, że tab1 i tab2 mają kolumny Id, Name i Remark, a tab2 ma więcej kolumn Wersja wiersza niż tab1.
Najpierw dołącz kod testowy:
【ConcurrencyCheck Principle】
Dodaliśmy funkcję ConcurrencyCheck do właściwości Remark w Tab1,
Gdy aktualizujemy wartość atrybutu Name tych samych danych w tym samym czasie, nie pojawia się żaden wyjątek!
Generuj instrukcje SQL:
exec sp_executesql N'UPDATE [dbo]. [Tab1] SET [Nazwa] = @0 GDZIE (([Id] = @1) ORAZ ([Uwaga] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'name1',@1=1,@2=N'Note1' exec sp_executesql N'UPDATE [dbo]. [Tab1] SET [Nazwa] = @0 GDZIE (([Id] = @1) ORAZ ([Uwaga] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'name2',@1=1,@2=N'note1' Gdy aktualizujemy wartość właściwości Remark dla tych samych danych w tym samym czasie, rzucamy wyjątek!
Generuj instrukcje SQL:
exec sp_executesql N'UPDATE [dbo]. [Tab1] USTAW [Uwaga] = @0 GDZIE (([Id] = @1) ORAZ ([Uwaga] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Note1',@1=1,@2=N'Note' exec sp_executesql N'UPDATE [dbo]. [Tab1] USTAW [Uwaga] = @0 GDZIE (([Id] = @1) ORAZ ([Uwaga] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Note 2',@1=1,@2=N'Note' Możemy zauważyć, że jeśli jednocześnie weźmiemy ten sam fragment danych z Id 1, otrzymamy wartość atrybutu Remark, a podczas aktualizacji atrybutu Remark użyjemy Remark jako warunek aktualizacji.
Pierwsze polecenie SQL można pomyślnie zaktualizować, a następnie uwaga zostaje zmieniona na "note 1", a gdy druga instrukcja SQL zostanie zaktualizowana, aktualizacja nie powiodła się, ponieważ wartość uwagi się zmieniła.
【Zasada znaczników czasu】
Dodaliśmy właściwość RowVersion do Tab2 (możesz przyjąć dowolną nazwę) oraz dodaliśmy funkcję Timestamp!!
Gdy aktualizujemy wartość Name tych samych danych w tym samym czasie, pierwsza aktualizacja się powiodła, druga kończyła się niepowodzeniem i pojawiał się wyjątek – przyjrzyjmy się wygenerowanemu kodowi SQL!
exec sp_executesql N'UPDATE [dbo]. [Tab2] SET [Nazwa] = @0 GDZIE ((([Id] = @1) AND ([RowVersion] = @2)) ORAZ ([Remark] = @3)) WYBIERZ [RowVersion] FROM [dbo]. [Tab2] GDZIE @@ROWCOUNT > 0 And [Id] = @1',N'@0 nvarchar(max) ,@1 int,@2 binarny(8),@3 nvarchar(max) ',@0=N'Name1',@1=1,@2=0x00000000000007D1,@3=N'Note' exec sp_executesql N'UPDATE [dbo]. [Tab2] SET [Nazwa] = @0 GDZIE ((([Id] = @1) AND ([RowVersion] = @2)) ORAZ ([Remark] = @3)) WYBIERZ [RowVersion] FROM [dbo]. [Tab2] GDZIE @@ROWCOUNT > 0 And [Id] = @1',N'@0 nvarchar(max) ,@1 int,@2 binary(8),@3 nvarchar(max) ',@0=N'name2',@1=1,@2=0x00000000000007D1,@3=N'Note' Podczas wykonywania drugiego polecenia SQL, ponieważ dane z warunku where nie są już dostępne, aktualizacja się nie udaje i wyrzucany jest wyjątek!!
Po pomyślnym wykonaniu pierwszego polecenia sql wartość RowVersion zmieni się, jak pokazano na poniższym rysunku:
Wersja RowsVersion to znacznik czasu
Obejście brakujących aktualizacji
Koncepcja brakujących aktualizacji: Gdy użytkownicy modyfikują linię danych jednocześnie, najpierw odczytują dane, umieszczają je na froncie do modyfikacji, a następnie przesyłają dane po modyfikacji, tak aby ostateczne przesłane dane nadpisywały wcześniej przesłane dane, co powoduje utratę aktualizacji.
Krótko mówiąc, oto sposoby, by uniknąć utraty aktualizacji:
Użyj znacznika czasu RowsVersion.
Jeśli wiersz jest niezgodny z wartością sprzed odczytu, oznacza to, że inna transakcja zaktualizowała tę kolumnę, przez co ta kolumna nie może być aktualizowana, co zapobiega utracie aktualizacji.
Na koniec dołącz kod źródłowy:
CodeFirstDemo.rar
(4.94 KB, Liczba pobranych plików: 13)
|