2012-12-19 19 views
12

C'è un motivo per non utilizzare dynamic-insert/dynamic-update per NHibernate? L'unica ragione che chiedo è che sembra essere qualcosa che vorrei abilitato come predefinito, non come qualcosa che dovrei configurare.NHibernate dynamic-update Svantaggi?

Ci sono dei trucchi da sapere quando si utilizzano queste proprietà dinamiche?

risposta

23

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.

+0

Molto informativo. Non ero nemmeno a conoscenza di select-before-update. Lo terremo sicuramente a mente. – Sam

+2

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. –

+0

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. –

5

L'inserimento e l'aggiornamento dinamici presentano un leggero costo in termini di prestazioni poiché NHibernate deve creare l'SQL ogni volta invece di memorizzarlo nella cache. Non so se c'è un costo sul lato del database. Inserimento e aggiornamento dinamici sono molto utili per la risoluzione dei problemi e la profilazione. Se fossi in grado di misurare un impatto significativo sulle prestazioni, lo accenderei in sviluppo e fuori produzione.

È possibile che si verifichino problemi con gli ascoltatori e gli intercettori, vedere this question.

L'ho attivato nelle mie applicazioni NHibernate senza problemi. La mia risposta è no, non c'è una buona ragione per non usarlo.

+0

Curioso sui tuoi commenti sulla memorizzazione nella cache. Quando guardo l'SQL generato usando log4net, sembra che stia usando query parametrizzate. Quelli non saranno ancora memorizzati da qualche parte lungo la linea? Inoltre, non lasciare le query dinamiche disattivate ha anche un impatto sulle prestazioni aggiornando i campi che non sono stati modificati? O è un costo trascurabile? Grazie per il feedback. – Sam

+2

NHibernate può memorizzare nella cache un formato di query statico in modo che la creazione di una query stia semplicemente riempiendo gli spazi vuoti. Con query dinamiche, la query deve essere costruita ogni volta. Il problema di prestazioni dell'aggiornamento di tutti i campi, se esiste, dipende dal database. Ci sono una serie di fattori, ma la mia opinione e esperienza mi consiglia di utilizzare inserimenti e aggiornamenti dinamici. –