Per alcune entità, è possibile creare uno stato non valido tramite gli aggiornamenti dinamici. Supponiamo che tu abbia un Class
con una Boolean
di proprietà A
e una proprietà Integer
dipendente logicamente B
. Se la proprietà A
è True
, la proprietà B
può essere solo un numero negativo, mentre se la proprietà A
è False
, la proprietà B
può essere solo un numero positivo.
Supponiamo che due utenti interagiscano con un'istanza di questa classe in un determinato intervallo di tempo. Per cominciare, gli utenti Alice e Bob sia materializzano questa classe dal database, con i valori iniziali di A
= True e B
= -50
Database Alice Bob
A: True A: True A: True
B: -50 B: -50 B: -50
VALID VALID VALID
Alice utente cambia A
-False
e B
-125, e lo commette al database. Ora abbiamo questa situazione:
Database Alice Bob
A: False A: False A: True
B: 125 B: 125 B: -50
VALID VALID VALID
utente Bob non cambia A
, ma cambia B
a -75, poi impegna al database. Se gli aggiornamenti dinamici sono attivi, allora NHibernate rileva che Bob ha modificato solo B
a -75 e emette un aggiornamento dinamico che modifica solo il valore di B
. Se sul server era presente la convalida SQL per impedire che B
fosse negativo a meno che lo A
non fosse vero, si otterrebbe un errore SQL qui, ma supponiamo che non sia stata riprodotta tutta la logica aziendale sulle tabelle SQL. Ecco i dati risultanti:
Database Alice Bob
A: False A: False A: True
B: -75 B: 125 B: -75
INVALID VALID VALID
Sia Alice che Bob hanno stati validi, ma il database è ora in uno stato non valido! Utente Charlie arriva e cerca di materializzare questo record:
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 sarebbe probabilmente ottenere un errore di convalida dall'applicazione quando NHibernate ha cercato di impostare la proprietà B della nuova istanza della classe.
Quindi, quando si dispone di proprietà logicamente dipendenti, è necessario disporre di una strategia in atto per evitare questa situazione. Una possibilità è semplicemente abilitare select-before-update
per questa entità. Ciò può comportare alcune chiamate al database aggiuntive e prestazioni un po 'più lente. Un altro è utilizzare il controllo delle versioni in NHibernate, il che significherebbe che quando Bob cerca di salvare il suo record, la query di inserimento di NHibernate non attiverà alcuna scrittura e genererà un'eccezione di dati obsoleti (che può essere gestita con garbo). Puoi anche codificare i requisiti logici della tua classe nel database, tuttavia dovrai essere cauto per assicurarti che il database e il programma abbiano entrambi gli stessi requisiti codificati col passare del tempo, e avrai più posti per apportare modifiche quando cambiano i requisiti, che non è sempre un overhead utile.
Quindi, in breve, in molte circostanze uno sviluppatore deve gestire attentamente i dettagli degli aggiornamenti dinamici, motivo per cui non è attivo per impostazione predefinita.Quando lo accendi, considera se gli aggiornamenti parziali della tua entità potrebbero causare problemi e, in tal caso, utilizzare una delle strategie di attenuazione che ho consigliato di proteggere da tale problema.
Molto informativo. Non ero nemmeno a conoscenza di select-before-update. Lo terremo sicuramente a mente. – Sam
In questo esempio l'applicazione ha consentito all'utente di eseguire il commit delle modifiche mentre l'entità era in uno stato non valido. La classe dovrebbe incapsulare l'accesso a tali proprietà in modo che la regola aziendale venga applicata e/o l'entità debba essere convalidata prima che la transazione venga eseguita. Non vedo che questo abbia qualcosa a che fare con l'aggiornamento dinamico. –
Ti manca la lezione qui: la copia di Bob dell'entità non era in uno stato non valido. L'entità non è più valida quando l'aggiornamento dinamico ha modificato il valore della proprietà B senza avere l'informazione che il valore persistente della proprietà A avrebbe reso tale valore non valido. –