2009-06-23 12 views
17

Mi sto divertendo un sacco di tempo a cercare di capire i miei problemi di gestione delle sessioni in NHibernate. Presumo che molti dei miei problemi siano dovuti alla mancanza di conoscenza dei concetti di IoC e AOP; almeno questo è quello che sto pensando da dove Fabio Maulo continua a dirigermi.Gestione delle sessioni NHibernate e caricamento lazy

In ogni caso, il mio problema è che ho un'applicazione di moduli di vincita che sta effettuando chiamate "get" e vincolando il risultato a una griglia. Dopo l'associazione, l'utente può eseguire una sorta di azione di "scrittura" e questi determinano la chiusura della sessione dopo la scrittura nel tentativo di utilizzare il concetto di sessione per uso. Quindi l'utente può scorrere la griglia che fa partire il caricamento lento e ora la sessione è stata chiusa e ottengo un'eccezione.

Non voglio rendere il mio punto di vista consapevole delle mie sessioni, non voglio inviare una KillAllSessions quando l'utente chiude il modulo. Inoltre, un utente può avere più moduli aperti in qualsiasi momento ulteriormente aggravando i problemi associati a tale metodo. In sostanza, voglio che tutto questo funzioni "dietro le quinte".

Quindi la mia idea finora è quella di intercettare la pigra chiamata di caricamento e verificare se la sessione è aperta e se non la riapri, ottenere le informazioni e richiuderle. Tuttavia, per quanto posso dire, che non è molto, questo è essenzialmente il modo in cui il caricamento pigro funziona comunque. Viene intercettato dalla factory proxy (NHibernate.Bytecode.Castle) e quindi recupera i dati utilizzando la sessione. Quindi ho bisogno di intercettare effettivamente quella chiamata e poi passarla all'intercetta originale dopo aver riaperto la sessione. Questa è la mia idea.

La mia domanda è essenzialmente prima di tutto questo è anche il modo giusto per andare su questo? In secondo luogo, se lo è, non so nemmeno da dove cominciare. Non ho mai fatto intercettazioni di chiamate di metodo, ne ero a conoscenza in teoria ma non in pratica. So che ci sono biblioteche là fuori che fanno questo genere di cose come Rhino Commons, ma voglio cogliere questa opportunità per imparare e diventare un programmatore migliore. Sto cercando di capire AOP e Context Bound Objects ma al momento non lo sto facendo. Qualcuno di voi potrebbe aiutare un ragazzo a uscire?

+0

Sembra una cosa molto strana da fare. La sessione deve essere eliminata dopo la chiusura. Puoi fare un esempio? – Paco

+0

Mi dispiace, quale parte sembra strana? Per quanto riguarda un esempio, non so nient'altro che fornirti la sequenza di eventi che mi ha fatto affrontare questo problema: 1. Open Session 2. Ottieni dati sotto forma di IList 3. Compila un ITyp personalizzato collezione 4. Bind to datagrid 5. Una modifica arbitraria viene effettuata 6. Questa modifica richiede una sessione 7. Il gestore della sessione assegna la sessione già aperta 8. Poiché è una funzione di scrittura, chiude la sessione una volta terminata 9. L'utente inizia a scorrere la griglia causando il caricamento lazy per verificarsi 10. Viene generata un'eccezione perché la sessione non è più aperta – joshlrogers

+0

Perché il caricamento lento si verifica durante lo scorrimento? – Paco

risposta

7

mi viene in mente un paio di opzioni:

Opzione 1: Mantenere l'originale ISession aperto mentre l'utente interagisce con i dati e si impegnano tutti i cambiamenti in una volta quando l'utente è fatto. Ciò significa che potresti avere un gran numero di modifiche non salvate in memoria e che gli altri utenti non vedranno cambiamenti in sospeso.

Opzione 2: Dividere le operazioni in due unità di lavoro (UOW). UOW1 legge solo ed è responsabile per compilare la lista. L'ISessione associata a UOW1 rimane attiva per consentire il caricamento lazy, ad esempio in uno scenario di drill-down. UOW2 è una nuova ISIONE di breve durata creata per le modifiche dell'utente. Quando una modifica viene eseguita, l'oggetto originale viene rimosso da UOW1 e UOW1 recupera una nuova copia dal database.

Opzione 3: Ricrea l'elenco dopo ogni modifica commessa. Questa è la soluzione più semplice e potrebbe essere adatta per piccoli set di dati.

+0

James, grazie per la risposta, ho una domanda però. Con l'opzione 1 e 2, come chiuderei la sessione dopo "ottieni" senza che la vista inviasse un messaggio di Kill al Gestore della Sessione dicendogli che l'utente sta chiudendo l'applicazione o il modulo? – joshlrogers

+0

Non so abbastanza della tua architettura per commentare. Tuttavia, sembra che l'unità di confine del lavoro sarebbe quando il modulo è chiuso. Penso che sia molto meglio gestire localmente la durata della sessione piuttosto che avere un gestore di sessione globale che ha responsabilità oltre a creare nuove sessioni. –

+0

Sono andato con una variante dell'opzione 2 - mantenendo aperta la sessione UOW1 per consentire alla griglia di caricarsi lentamente mentre l'utente naviga. Ma gestire le sessioni individuali per fare modifiche ecc. È stato molto difficile. Mi piace molto l'idea di Josh di creare una sessione al volo per servire un carico pigro ogni volta che si accede ai dati. –

2

Sto lavorando a un'applicazione simile. Sto usando una sessione che tengo aperta.

Ogni volta che scrivo nel database, utilizzo la transazione begin/commit che non chiude la sessione sottostante. la connessione al database è aperta solo da NHibernate mentre la transazione è in corso.

C'è un motivo per cui è necessario chiudere la sessione mentre l'utente sta utilizzando attivamente il modulo?

Potete fornire maggiori dettagli su ciò che state utilizzando per gestire la sessione, il modello di repository, ... ecc.?

+0

Perché sto cercando di mantenere il mio punto di vista per essere consapevole del mio DAL o di qualsiasi suo funzionamento. La mia sessione era gestita da un modello singleton prima che mi capitasse questo problema. – joshlrogers

+0

Creo la mia sessione/repository tramite StructureMap e solo il modello li utilizza. La mia opinione non è consapevole della persistenza. – Maggie

+0

Ricorda che ci sono dei rischi nel mantenere aperta una sessione per tutta la vita dell'app. Le prestazioni possono risentirne negativamente, in particolare con gli aggiornamenti, se carichi centinaia di entità attraverso una singola sessione. –

Problemi correlati