NHibernate ISession Flush: dove e quando usarlo e perché?

Una delle cose che mi confondono completamente è l’uso di session.Flush , in congiunzione con session.Commit e session.Close .

A volte session.Close funziona, ad esempio, impegna tutte le modifiche di cui ho bisogno. So che ho bisogno di usare commit quando ho una transazione, o un’unità di lavoro con diverse crea / aggiornamenti / eliminazioni, in modo che possa scegliere di eseguire il rollback se si verifica un errore.

Ma a volte sono davvero ostacolato dalla logica dietro la session.Flush . session.Flush . Ho visto esempi in cui hai una session.SaveOrUpdate() seguita da un flush, ma quando togli Flush funziona comunque. A volte mi imbatto in errori nella dichiarazione Flush che dicono che la sessione è scaduta, e rimuoverla mi ha assicurato che non ho incontrato quell’errore.

Qualcuno ha una buona linea guida su dove o quando usare una scala? Ho controllato la documentazione di NHibernate per questo, ma non riesco ancora a trovare una risposta semplice.

Brevemente:

  1. Usa sempre le transazioni
  2. Non utilizzare Close() , invece di avvolgere le chiamate su ISession all’interno di un’istruzione using o gestire il ciclo di vita della tua ISession da qualche altra parte .

Dalla documentazione :

Di volta in volta l’ ISession eseguirà le istruzioni SQL necessarie per sincronizzare lo stato della connessione ADO.NET con lo stato degli oggetti contenuti nella memoria. Questo processo, a livello, si verifica di default nei seguenti punti

  • da alcune invocazioni di Find() o Enumerable()
  • da NHibernate.ITransaction.Commit()
  • da ISession.Flush()

Le istruzioni SQL sono emesse nel seguente ordine

  1. tutte le inserzioni di quadro, nello stesso ordine gli oggetti corrispondenti sono stati salvati utilizzando ISession.Save()
  2. tutti gli aggiornamenti di quadro
  3. tutte le eliminazioni della collezione
  4. tutte le eliminazioni, gli aggiornamenti e gli inserimenti degli elementi di raccolta
  5. tutti gli inserimenti di raccolta
  6. tutte le cancellazioni di quadro, nello stesso ordine gli oggetti corrispondenti sono stati cancellati usando ISession.Delete()

(Un’eccezione è che gli oggetti che utilizzano la generazione di ID nativo vengono inseriti quando vengono salvati).

Tranne quando esplicitamente Flush() , non ci sono assolutamente garanzie circa quando la Session esegue le chiamate ADO.NET, solo l’ordine in cui vengono eseguite . Tuttavia, NHibernate garantisce che i ISession.Find(..) non restituiranno mai dati ISession.Find(..) ; né restituiranno i dati sbagliati.

È ansible modificare il comportamento predefinito in modo che lo svuotamento avvenga meno frequentemente. La class FlushMode definisce tre diverse modalità: solo flush al tempo di commit (e solo quando viene utilizzata l’API ITransaction NHibernate), svuota automaticamente usando la routine spiegata, o non esegue mai il flush a meno che Flush() venga chiamato esplicitamente. L’ultima modalità è utile per unità di lavoro di lunga durata, in cui una ISession viene mantenuta aperta e disconnessa per un lungo periodo di tempo.

Vedi anche questa sezione :

La fine di una sessione comporta quattro fasi distinte:

  • irrigare la sessione
  • impegnare la transazione
  • chiudi la sessione
  • gestire le eccezioni

Flushing the Session

Se ti capita di utilizzare l’API ITransaction , non devi preoccuparti di questo passaggio. Sarà eseguito implicitamente al momento della transazione. Altrimenti dovresti chiamare ISession.Flush() per assicurarti che tutte le modifiche siano sincronizzate con il database.

Commettere la transazione del database

Se stai usando l’API ITransaction di NHibernate, sembra che:

 tx.Commit(); // flush the session and commit the transaction 

Se si gestiscono le transazioni ADO.NET da soli, è necessario eseguire manualmente il commit Commit() della transazione ADO.NET.

 sess.Flush(); currentTransaction.Commit(); 

Se decidi di non confermare le tue modifiche:

 tx.Rollback(); // rollback the transaction 

o:

 currentTransaction.Rollback(); 

Se si esegue il rollback della transazione, chiudere immediatamente la sessione corrente e ignorarla per assicurarsi che lo stato interno di NHibernate sia coerente.

Chiusura dell’ISession

Una chiamata a ISession.Close() segna la fine di una sessione. L’implicazione principale di Close () è che la connessione ADO.NET verrà abbandonata dalla sessione.

 tx.Commit(); sess.Close(); sess.Flush(); currentTransaction.Commit(); sess.Close(); 

Se hai fornito la tua connessione, Close() restituisce un riferimento, in modo da poterlo chiudere manualmente o restituirlo al pool. Altrimenti Close() restituisce al pool.

A partire da NHibernate 2.0, le transazioni sono necessarie per le operazioni DB. Pertanto, la chiamata ITransaction.Commit() gestirà qualsiasi flushing necessario. Se per qualche motivo non stai utilizzando le transazioni di NHibernate, non ci sarà alcuno scarico automatico della sessione.

Di volta in volta l’ISession eseguirà le istruzioni SQL necessarie per sincronizzare lo stato della connessione ADO.NET con lo stato degli oggetti contenuti nella memoria.

E usa sempre

  using (var transaction = session.BeginTransaction()) { transaction.Commit(); } 

dopo che le modifiche sono state commesse rispetto a queste modifiche per salvare nel database usiamo transaction.Commit ();

Ecco due esempi del mio codice dove fallirebbe senza session.Flush ():

http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html

alla fine di questo, puoi vedere una sezione di codice in cui imposto l’inserimento dell’id quadro, salvare l’ quadro, quindi svuotare, quindi distriggersre l’inserimento dell’identity framework. Senza questo flush sembrava impostare l’inserimento dell’id quadro e quindi salvare l’entity framework.

L’uso di Flush () mi ha dato più controllo su quello che stava succedendo.

Ecco un altro esempio:

Invio del messaggio NServiceBus all’interno di TransactionScope

Non capisco perfettamente perché su questo, ma Flush () ha impedito il mio errore.