2010-01-06 17 views
41

Sono nuovo di NHibernate e ho riscontrato alcuni problemi durante la chiusura prematura delle sessioni. L'ho risolto temporaneamente riutilizzando le sessioni invece di aprire una sessione per transazione. Tuttavia, avevo l'impressione che aprire le sessioni ogni volta che ne avessi bisogno fosse l'approccio consigliato per la gestione della durata della sessione. No?Quale dovrebbe essere la durata di una sessione di NHibernate?

Quindi; qual è il modo consigliato di gestire le sessioni? Quale dovrebbe essere la loro vita? Una transazione di sessione? Una sessione singleton per gestire tutto? O cosa?

Edit:

Nota che la mia architettura delle applicazioni è un'applicazione desktop che comunica con un servizio lato server, che è ciò che fa tutto la gestione di database, utilizzando NHibernate + Fluent. (Se questo fa alcuna differenza ...)

+2

Nella tua domanda http://stackoverflow.com/questions/2011950/nhibernate-mappings-issue-when-referencing-class-lazy-load-issue mi hai chiesto di esaminare questa nuova domanda, ma ti vedo " Ho già ricevuto un'ampia copertura. In secondo luogo, qui ho alcune opinioni, ma sappi che sembra che sessioni e transazioni siano mescolate nella discussione, mentre quelle sono cose diverse. Inoltre, un pool di sessioni o una sessione attivata dal timeout può essere utile in termini di prestazioni, ma difficile da configurare e ottenere correttamente. Si noti inoltre che sotto il cofano, il pool di connessioni viene utilizzato indipendentemente dal modello scelto. – Abel

+0

Grazie per il tuo commento Abel. Negli esempi ho visto sessioni e transazioni spesso condividono la stessa durata, ma come visto nella domanda di riferimento questo può essere un problema a volte .. Spero che le persone abbiano risposto a "durata della sessione" - non "durata della transazione", l'impressione che sia così. – stiank81

risposta

26

Si desidera una strategia di gestione delle sessioni che consenta all'app di funzionare in modo efficace e sfruttare le funzionalità offerte da NHibernate, in particolare il caricamento nella cache e il caricamento lento.

Creazione di sessioni è un processo poco costoso e richiede poca RAM o CPU in anticipo, quindi non dovresti preoccuparti di conservare o riutilizzare le sessioni (in effetti, riutilizzarle può portare a un lato sgradevole e non previsto -Effetti). La factory di sessione è la cosa costosa e dovrebbe essere creata una sola volta all'avvio dell'app.

La regola generale è questa: la durata della sessione deve essere sufficientemente lunga da non avere oggetti persistenti in giro dopo l'interruzione della sessione.

Una volta che al termine della sessione, tutti i cambiamenti di monitoraggio per gli oggetti avete ottenuto dal quella sessione si ferma, quindi tali modifiche non vengono salvate a meno che deliberatamente ricollegare l'oggetto a una nuova sessione. La sessione dovrebbe quindi essere in giro fino a quando esisteranno gli oggetti che recupererai. In un'app Web, generalmente si intende una sessione per ogni richiesta; in WinForms, una sessione per ogni modulo.

Nel tuo caso, con un servizio di (presumo è in esecuzione come un servizio di Windows) facendo il lavoro NHibernate, si potrebbe prendere in considerazione che ha una sessione creata per ogni nuova richiesta da parte del consumo di un'applicazione desktop, e lo smaltimento è quando tale richiesta è stata revisionata. Non sapendo esattamente come funziona il tuo servizio e quale meccanismo l'app desktop usa per parlarci (remoting? WCF? Plain old SOAP?) Non posso davvero essere più specifico.

(Esistono alcune eccezioni a questa regola generale - si supponga di disporre di un set di oggetti persistenti che rappresentano una risorsa condivisa a cui altri codici si riferiscono ma non cambiano, è possibile caricare questi in primo piano all'avvio dell'app e lasciare da lì in poi.)

Se si riscontrano prestazioni lente in una tale strategia, è possibile che si stia parlando troppo con il database e che il grafico dell'oggetto sia complesso; guarda second-level caching in questo caso.

+0

Grazie!Per quanto riguarda il mio servizio, sto usando WCF, attualmente con soap - che funziona come un'applicazione per console, ma non credo che questo dovrebbe fare alcuna differenza, quindi sei stato abbastanza specifico. Sembra ragionevole avere una sessione per ogni richiesta. Attualmente sto solo utilizzando una sessione in cui viene eseguita la transazione, e sembra che ci siano alcuni dati di riferimento che non vengono caricati durante la transazione che non riesce perché la sessione è chiusa. – stiank81

6

Una sessione deve corrispondere a un'unità di lavoro. La sessione dovrebbe rimanere in vita mentre si lavora con gli oggetti recuperati o persistenti utilizzando quella sessione.

0

Gran parte del framework NHibernate e Microsoft ADO.NET Entity Framework sono simili. Ecco un ottimo articolo su come si dovrebbe controllare una linea di vita ObjectContext in EF ADO.NET.

http://blogs.msdn.com/alexj/archive/2009/05/07/tip-18-how-to-decide-on-a-lifetime-for-your-objectcontext.aspx

Si dovrebbe valere per le sessioni di NHibernate pure.

+1

A mio parere, poiché EF 1.0/3.5 non supporta il caricamento lazy basato su proxy automatico, le differenze tra EF e NHibernate in relazione a questo problema sono troppo grandi per condividere efficacemente i consigli. La durata di ObjectContext in EF è più semplice da gestire perché EF non è ricco di funzionalità. –

+0

Hai ragione che EF 1.0 non lo supporta, ma l'EF 2.0 lo fa. Questo articolo sembra applicarsi a entrambi. –

11

In un'app Web, è necessario disporre di una sessione per richiesta. Questo ti dà il pieno controllo sulla durata della sessione e semplifica la gestione degli errori.

In un'applicazione desktop, si consiglia di utilizzare una sessione per presentatore (o modulo se si preferisce). Per citare Ayende nel suo MSDN Magazine article:

La procedura consigliata per il tavolo applicazioni è quello di utilizzare una sessione per forma, in modo che ogni modulo nell'applicazione ha una propria sessione. Ogni modulo di solito rappresenta una distinta parte di lavoro che l'utente desidera eseguire da , pertanto la durata corrispondente della durata della durata del modulo funziona in modo ottimale con lo . Il vantaggio aggiunto è che non si ha più un problema con perdite di memoria, perché quando si chiude un modulo nell'applicazione , si dispone anche della sessione . Ciò renderebbe tutte le entità caricate dalla sessione idonee per il recupero da parte di il Garbage Collector (GC).

Ci sono altri motivi per preferendo una singola sessione per modulo. È possibile sfruttare il rilevamento delle modifiche di NHibernate, in modo da svuotare tutte le modifiche nel database quando si esegue il commit della transazione con .E 'anche crea una barriera di isolamento tra le diverse forme, in modo da poter commettere modifiche a una singola entità, senza preoccuparsi di modifiche ad altri entità che vengono visualizzati su altri forme.

+0

"sessione per operazione" è piuttosto vaga. Dovresti menzionare "sessione per richiesta" –

Problemi correlati