Domanda

Una delle cose che mi confonde completamente è l'uso di session.Flush,insieme a session.Commit, E session.Close.

A volte session.Close funziona, ad esempio, applica tutte le modifiche di cui ho bisogno.So che devo utilizzare commit quando ho una transazione o un'unità di lavoro con diverse creazioni/aggiornamenti/eliminazioni, in modo da poter scegliere di eseguire il rollback se si verifica un errore.

Ma a volte rimango davvero ostacolato dalla logica che sta dietro session.Flush.Ho visto esempi in cui hai a session.SaveOrUpdate() seguito da un flush, ma quando rimuovo Flush funziona comunque bene.A volte mi imbatto in errori nell'istruzione Flush che dicono che la sessione è scaduta e rimuovendola mi sono assicurato di non incorrere in quell'errore.

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

È stato utile?

Soluzione

Brevemente:

  1. Usa sempre le transazioni
  2. Non utilizzare Close(), avvolgi invece le tue chiamate in un ISession all'interno di un using dichiarazione o gestisci il ciclo di vita della tua sessione da qualche altra parte.

Da la documentazione:

Di tanto in tanto il ISession eseguirà le istruzioni SQL necessarie per sincronizzare lo stato della connessione ADO.NET con lo stato degli oggetti contenuti in memoria.Questo processo, flush, si verifica per impostazione predefinita nei seguenti punti

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

Le istruzioni SQL vengono emesse nel seguente ordine

  1. tutti gli inserimenti di entità, nello stesso ordine in cui sono stati salvati gli oggetti corrispondenti ISession.Save()
  2. tutti gli aggiornamenti dell'entità
  3. tutte le eliminazioni della raccolta
  4. tutte le eliminazioni, gli aggiornamenti e gli inserimenti degli elementi della raccolta
  5. tutti gli inserimenti della collezione
  6. tutte le eliminazioni di entità, nello stesso ordine in cui sono stati eliminati gli oggetti corrispondenti ISession.Delete()

(Un'eccezione è rappresentata dal fatto che gli oggetti che utilizzano la generazione di ID nativi vengono inseriti quando vengono salvati.)

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

È possibile modificare il comportamento predefinito in modo che lo svuotamento avvenga meno frequentemente.IL FlushMode La classe definisce tre diverse modalità:scarica solo al momento del commit (e solo quando NHibernate ITransaction viene utilizzata l'API), svuota automaticamente utilizzando la routine spiegata o non scarica mai a meno che Flush() viene chiamato esplicitamente.L'ultima modalità è utile per unità di lavoro di lunga durata, in cui un ISession rimane aperto e disconnesso per molto tempo.

...

Fare riferimento anche a questa sezione:

La conclusione di una sessione prevede quattro fasi distinte:

  • svuotare la sessione
  • commettere la transazione
  • chiudere la sessione
  • gestire le eccezioni

Svuotare la sessione

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

Commiting della transazione del database

Se stai utilizzando l'API NHibernate ITransaction, apparirà così:

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

Se gestisci tu stesso le transazioni ADO.NET, dovresti farlo manualmente Commit() la transazione ADO.NET.

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

Se decidi di non confermare le modifiche:

tx.Rollback();  // rollback the transaction

O:

currentTransaction.Rollback();

Se esegui il rollback della transazione dovresti chiudere immediatamente ed eliminare la sessione corrente per garantire che lo stato interno di NHibernate sia coerente.

Chiusura della sessione

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 ad esso, quindi puoi chiuderlo manualmente o restituirlo al pool.Altrimenti Close() lo restituisce alla piscina.

Altri suggerimenti

A partire da Hibernate 2.0, le transazioni sono necessarie per le operazioni del DB.quindi, il ITransaction.Commit() la chiamata gestirà qualsiasi svuotamento necessario.Se per qualche motivo non utilizzi le transazioni NHibernate, non verrà effettuato lo svuotamento automatico della sessione.

Di tanto in tanto la sessione eseguirà le istruzioni SQL necessarie per sincronizzare lo stato della connessione ADO.NET con lo stato degli oggetti contenuti in memoria.

E usalo sempre

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

dopo che le modifiche sono state confermate, queste modifiche vengono salvate nel database, utilizziamo Transaction.Commit();

Ecco due esempi del mio codice in cui 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'identità, salvo l'entità, quindi svuoto, quindi disattivo l'inserimento dell'identità.Senza questo svuotamento sembrava che si stesse attivando e disattivando l'inserimento dell'identità e quindi salvando l'entità.

L'uso di Flush() mi ha dato maggiore controllo su ciò che stava succedendo.

Ecco un altro esempio:

Invio del messaggio NServiceBus all'interno di TransactionScope

Non capisco appieno il motivo per cui su questo, ma Flush() ha impedito che si verificasse il mio errore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top