Dla niektórych podmiotów można utworzyć nieprawidłowy stan za pomocą aktualizacji dynamicznych. Załóżmy, że masz Class
o wartości Boolean
Właściwość A
i logicznie zależną od siebie. Jeśli właściwość A
to True
, właściwość B
może być tylko liczbą ujemną, natomiast jeśli właściwość A
to False
, wówczas właściwość B
może być tylko liczbą dodatnią.
Załóżmy, że dwóch użytkowników jednocześnie wchodzi w interakcję z wystąpieniem tej klasy w określonym przedziale czasu. Aby rozpocząć, użytkownicy Alicja i Bob zarówno urzeczywistnić tę klasę z bazy danych, z początkowych wartości A
= True i B
= -50
Database Alice Bob
A: True A: True A: True
B: -50 B: -50 B: -50
VALID VALID VALID
Alice użytkownik zmieni A
do False
i B
do 125, i zobowiązuje się je do bazy danych. Teraz mamy taką sytuację:
Database Alice Bob
A: False A: False A: True
B: 125 B: 125 B: -50
VALID VALID VALID
Użytkownik Bob nie zmienia A
, ale zmienia B
do -75, a następnie zobowiązuje go do bazy danych. Jeśli aktualizacje dynamiczne są włączone, to NHibernate widzi, że Bob zmienił tylko B
na -75 i wydaje dynamiczną aktualizację, która edytuje tylko wartość B
. Jeśli sprawdzanie poprawności SQL na serwerze uniemożliwiłoby uzyskanie wartości ujemnej B
, o ile nie podano wartości A
, wystąpiłby błąd SQL, ale załóżmy, że nie powielono całej logiki biznesowej na tabelach SQL. Oto wynikowe dane:
Database Alice Bob
A: False A: False A: True
B: -75 B: 125 B: -75
INVALID VALID VALID
Zarówno Alicja jak i Bob mają prawidłowe stany, ale Baza danych jest teraz w nieprawidłowym stanie! Użytkownik Charlie przychodzi i próbuje urzeczywistnić ten rekord:
Database Alice Bob Charlie
A: False A: False A: True A: False
B: -75 B: 125 B: -75 B: -75
INVALID VALID VALID INVALID
Charlie prawdopodobnie pojawia się błąd walidacji z aplikacji podczas NHibernate próbował ustawić właściwość B nowej instancji klasy.
Tak więc, jeśli masz właściwości zależne logicznie, musisz mieć pewną strategię, aby uniknąć tej sytuacji. Jedną z możliwości jest po prostu włączyć select-before-update
dla tego obiektu. Może to spowodować dodatkowe wywołania bazy danych i nieco wolniejszą wydajność. Innym sposobem jest wykorzystanie wersji w NHibernate, co oznaczałoby, że gdy Bob spróbuje zapisać swój rekord, zapytanie wstawiania NHibernate nie wyzwoli żadnych zapisów i wyrzuci wyjątek danych stałych (który może być z wdziękiem obsłużony). Możesz również skodyfikować wymagania logiczne swojej klasy w bazie danych, jednak musisz zachować ostrożność, aby upewnić się, że baza danych i program mają te same skodyfikowane wymagania co czas, a będziesz mieć wiele miejsc do wprowadzaj zmiany, gdy zmieniają się wymagania, co nie zawsze jest opłacalne.
Krótko mówiąc, w wielu okolicznościach programista musi ostrożnie obsługiwać szczegóły aktualizacji dynamicznych, dlatego nie jest domyślnie włączony.Po włączeniu należy rozważyć, czy częściowe aktualizacje jednostki mogą spowodować problemy, a jeśli tak, to użyj jednej ze strategii łagodzenia zalecanych w celu ochrony przed tym problemem.
Bardzo przydatne. Nie wiedziałem nawet o wyborze przed aktualizacją. Z pewnością o tym pamiętam. – Sam
W tym przykładzie aplikacja zezwoliła użytkownikowi na zatwierdzenie zmian, gdy jednostka była w niepoprawnym stanie. Klasa powinna hermetyzować dostęp do tych właściwości, aby reguła biznesowa została wymuszona i/lub jednostka powinna zostać zatwierdzona przed zatwierdzeniem transakcji. Nie widzę, aby miało to coś wspólnego z aktualizacją dynamiczną. –
Brakuje ci lekcji: kopia istoty Boba nie była w nieprawidłowym stanie. Jednostka stała się nieważna tylko wtedy, gdy aktualizacja dynamiczna zmieniła wartość właściwości B bez informacji, że utrwalona wartość właściwości A spowodowałaby niepoprawną wartość. –