2010-05-08 7 views

risposta

18

Non ho molta familiarità con il modo in cui devono essere gestite le sessioni di NHibernate. Detto questo, Autofac ha un'eccellente gestione della durata dell'istanza (scoping e deterministic disposal). Alcune risorse correlate sono this article e this question. Dato che ti trovi in ​​ASP.Net MVC land assicurati di controllare anche in the MVC integration stuff.

Per illustrare questo punto, ecco un rapido esempio su come è possibile utilizzare autofac delegati di fabbrica e il Owned generica per avere il pieno controllo su istanza vita:

public class SomeController 
{ 
    private readonly Func<Owned<ISession>> _sessionFactory; 

    public SomeController(Func<Owned<ISession>> sessionFactory) 
    { 
     _sessionFactory = sessionFactory; 
    } 

    public void DoSomeWork() 
    { 
     using (var session = _sessionFactory()) 
     { 
      var transaction = session.Value.BeginTransaction(); 
      .... 
     } 
    } 
} 

La configurazione del contenitore per arrivare a questo lavoro è abbastanza semplice. Si noti che non abbiamo a che fare qualsiasi cosa per ottenere i tipi Func<> e Owned<>, questi sono messi a disposizione automaticamente dal Autofac:

builder.Register(c => cfg.BuildSessionFactory()) 
    .As<ISessionFactory>() 
    .SingleInstance(); 
builder.Register(c => c.Resolve<ISessionFactory>().OpenSession()); 

Aggiornamento: il mio ragionamento è che, secondo this NHibernate tutorial, la durata di l'istanza di sessione dovrebbe essere quella della "unità di lavoro". Quindi abbiamo bisogno di un modo per controllare sia quando l'istanza di sessione viene creata e quando la sessione viene eliminata.

Con Autofac otteniamo questo controllo richiedendo un Func<> invece del tipo direttamente. Se non si utilizza Func<>, è necessario che l'istanza di sessione venga creata in anticipo prima che venga creata l'istanza del controllore.

Successivamente, il valore predefinito in Autofac è che le istanze hanno la durata del contenitore. Poiché sappiamo che abbiamo bisogno del potere di disporre questa istanza non appena l'unità di lavoro è terminata, richiediamo un'istanza Owned. Smaltendo l'istanza di proprietà, in questo caso verrà immediatamente eliminata la sessione sottostante.

+1

Hmm ... Vorrei che le persone dessero delle critiche costruttive quando fanno un downvote. –

+0

Anch'io! :) Grazie per la tua risposta - Sto dando un'occhiata ai tuoi suggerimenti – UpTheCreek

+0

Ciao, ho capito tutto qui a partire dal Func > - Perché usare questo? Perché non solo iniettare nell'ISession standard? Non sono sicuro di aver veramente capito cosa fa il func/Owned, ma secondo la documentazione di autofac, se lo usi devi gettare manualmente l'oggetto? Un componente che ottiene i riferimenti a Owned è responsabile della chiamata Owning .Disponi quando l'istanza non è più necessaria. È un errore non pulire le istanze di proprietà. http://code.google.com/p/autofac/wiki/NewInV2 – UpTheCreek

0

Modifica: Suoni come Autofac e probabilmente altri contenitori possono avere una durata corretta della vita. Se è così, fallo.

Non è una buona idea utilizzare il contenitore IoC per gestire direttamente le sessioni. La durata della sessione deve corrispondere alla tua unità di lavoro (confine della transazione). Nel caso di un'applicazione web, quella dovrebbe quasi certamente essere la durata di una richiesta web.

Il modo più comune per ottenere ciò è con un HttpModule che crea la sessione e avvia la transazione quando inizia una richiesta, quindi esegue il commit al termine della richiesta. Vorrei che HttpModule registrasse la sessione nella collezione HttpContext.Items.

Nel contenitore IoC, è possibile registrare qualcosa come HttpContextSessionLocator contro ISessionLocator.

Devo menzionare che la gestione degli errori generica dovrebbe individuare la sessione corrente e ripristinare automaticamente la transazione, oppure si potrebbe finire per impegnare mezza unità di lavoro.

+4

* Perché * non è una buona idea? –

+1

D'accordo con James su questo, inserisco un'unità di fabbrica di lavoro nei miei controller (asp.net mvc) e creo un'unità di lavoro dall'interno del controller quando richiesto. La fabbrica è solo una classe wrapper (localizzatore di servizio) attorno al contenitore IoC (Structure Map) – AwkwardCoder

+0

@AWC: questo è esattamente quello che farei anch'io.La cosa è che il contenitore di Autofac ti dà le cose di fabbrica OOTB. –

Problemi correlati