7

Ho già sollevato questa domanda, ma sto ancora cercando di trovare un esempio che riesca a capirlo (per favore, non dirmi semplicemente di guardare al progetto S # arp Architecture senza almeno alcune indicazioni).Come posso implementare la sessione di NHibernate per richiesta senza una dipendenza su NHibernate?

Finora ho raggiunto l'ignoranza di persistenza nel mio progetto web. Le mie lezioni di repository (nel mio progetto di dati) prendono un'ISession nel costruttore:

public class ProductRepository : IProductRepository 
{ 
    private ISession _session; 
    public ProductRepository(ISession session) { 
     _session = session; 
    } 

Nel mio global.asax espongo la sessione corrente e sto creando e smaltimento sessione su BeginRequest e EndRequest (questo è dove ho la dipendenza da NHibernate):

public static ISessionFactory SessionFactory = CreateSessionFactory(); 

    private static ISessionFactory CreateSessionFactory() { 
     return new Configuration() 
      .Configure() 
      .BuildSessionFactory(); 
    } 

    protected MvcApplication() { 
     BeginRequest += delegate { 
      CurrentSessionContext.Bind(SessionFactory.OpenSession()); 
     }; 
     EndRequest += delegate { 
      CurrentSessionContext.Unbind(SessionFactory).Dispose(); 
     }; 
    } 

e infine il mio registro StructureMap:

public AppRegistry() { 
     For<ISession>().TheDefault 
      .Is.ConstructedBy(x => MvcApplication.SessionFactory.GetCurrentSession()); 

     For<IProductRepository>().Use<ProductRepository>(); 
    } 

sembrerebbe ho bisogno delle mie proprie implementazioni generiche di ISession e ISessionFactory che posso usare nel mio progetto web e iniettare nei miei repository?

Quindi, per chiarire, sto utilizzando NHibernate nel mio livello di repository e voglio utilizzare una richiesta di sessione per per (http). Quindi sto iniettando una ISession nei miei costruttori di repository (usando structuremap). Attualmente per creare e disporre le sessioni in ogni richiesta ho dovuto fare riferimento a NHibernate dal mio progetto web. Questa è la dipendenza che vorrei rimuovere.

Grazie, Ben

+6

NHibernate è secondo me non è una cattiva dipendenza. –

+0

Il mio progetto web comunica con il repository e NHibernate è una dipendenza del repository. Se non fosse per il fatto che volevo sessione per richiesta, potevo semplicemente aprire le mie sessioni all'interno del livello repository. Tuttavia, desidero una sessione per richiesta, ma non voglio che il mio progetto web sia legato a NHibernate. –

+2

Will Marcouiller: è ancora una dipendenza. Una dipendenza è una dipendenza. Cosa accadrebbe se Ben volesse trasferire la sua app su CouchDB o MongoDB o utilizzare un database di oggetti in memoria? –

risposta

3

Perché non creare un IHttpModule ed eseguire la vostra creazione e lo smaltimento lì (probabilmente nel Begin_Request ed eventi end_request), ma mette l'IHttpModule all'interno del progetto che ha la vostra dipendenza NHibernate . per esempio.

namespace MyWebApp.Repository.NHibernateImpl 
{ 
    public class NHibernateModule : IHttpModule 
    { 
     public void Init(HttpApplication context) 
     { 
      context.BeginRequest += new EventHandler(Context_BeginRequest); 
      context.EndRequest += new EventHandler(Context_EndRequest); 
     } 

     private void Context_BeginRequest(object sender, EventArgs e) 
     { 
      // Create your ISession 
     } 

     private void Context_EndRequest(object sender, EventArgs e) 
     { 
      // Close/Dispose your ISession 
     } 

     public void Dispose() 
     { 
      // Perhaps dispose of your ISessionFactory here 
     } 
    } 
} 

C'è forse un modo migliore, sono interessato a sapere anche questo, quindi qualche suggerimento alternativo?

+0

questa è la rotta in cui ho iniziato a scendere ma come te mi interessa se ci sono è un modo migliore (più DI amichevole) per farlo. –

+0

@ Ben - Ma non è una cattiva dipendenza cattiva in quanto non dovrai fare riferimento a questi oggetti da te né farne riferimento nel tuo progetto web. Tutto quello che devi fare è configurarlo nel tuo web.config. Qual è il problema?Se stavi configurando il tuo contenitore DI tramite XML, dovresti scriverlo anche tu. – jfneis

+0

@jfneis - hai un esempio completo di utilizzo di un HttpModule - Sono particolarmente interessato a come posso ancora iniettare la mia sessione nei repository e se le transazioni sono gestite in modo diverso. –

0

Grazie per l'aiuto di tutti finora. Un po 'più di ricerca mi ha portato al progetto di NHibernate Burrow.

Dal progetto FAQ (http://nhforge.org/wikis/burrow/faq.aspx):

Burrow è un middleware leggero sviluppato per supportare le applicazioni .Net utilizzando NHibernate (forse noto anche come NH in questo articolo) come framework ORM. L'utilizzo di Asp.net con NHibernate potrebbe rappresentare una sfida a causa del fatto che NHibernate è un ambiente con stato mentre Asp.net è un framework senza stato. Burrow può aiutare a risolvere questo conflitto fornendo una sessione avanzata e intelligente di gestione delle transazioni e altre facilitazioni.

Ho dovuto saltare qualche cerchio per farlo funzionare nel mio progetto. Dal momento che la versione corrente utilizza una vecchia versione di NHibernate ho dovuto scaricare il latest source dal trunk, aprire in VS, aggiungere riferimenti all'ultima versione di NHibernate e ricompilare (fortunatamente nessun errore).

Ho testato NHibernate Burrow in vari modi.

1) Continua l'iniezione ISession nei miei repository

Per fare questo, ho dovuto aggiungere i riferimenti a NHibernate, NHibernate.Burrow e NHibernate.Burrow.WebUtil al mio progetto MVC.

Nel web.config ho dovuto configurare Burrow (vedi http://nhforge.org/wikis/burrow/get-started.aspx) e poi nel mio registro StructureMap aggiungere il seguente:

 For<ISession>() 
      .TheDefault.Is 
      .ConstructedBy(x => new NHibernate.Burrow.BurrowFramework().GetSession());   

mi piace questo approccio in quanto significa mio repository (o controller) non sono accoppiato con Burrow. Non mi piace davvero il fatto di dover fare riferimento a questi tre assembly nel mio progetto web, ma almeno perdo il codice per la gestione della sessione - tutto questo è gestito da Burrow.

2) Il secondo approccio sarebbe quello di impostare ISession nei miei costruttori repository in questo modo:

public ProductRepository() : 
     this(new BurrowFramework().GetSession()) { } 

    public ProductRepository(ISession session) { 
     _session = session; 
    } 

posso ancora ignorare ISession fare i miei repository verificabile. Quindi ho una dipendenza diretta da Burrow ma forse non è una cosa così brutta?

Sul lato positivo, l'unico assembly che ho bisogno di fare riferimento dal mio progetto web è NHibernate.Burrow.WebUtils.

Interessato a vedere quale delle due persone sceglierebbe e perché.

2

Secondo me, dovresti abbracciare l'ISession e lavorare direttamente con esso. Il problema con molte implementazioni di sessioni per richiesta è che esse ritardano il commit delle modifiche al database fino alla fine della richiesta HTTP. Se la transazione fallisce, tutto ciò che puoi fare a quel punto è indirizzare l'utente a una pagina di errore generica. È molto meglio gestire la transazione sulla pagina in modo da poter intercettare e gestire gli errori in modo più efficace. Se si percorre questa strada, è necessario accedere all'ISession o a un wrapper per controllare la transazione.

Inoltre, a un certo punto l'applicazione avrà probabilmente bisogno di utilizzare proprietà o metodi esposti da ISession, in particolare Unisci e Carica.

+0

Cosa proponesti al posto della sessione per modello di richiesta? O stai suggerendo di non aprire una sessione e una transazione al momento dell'accattonaggio e poi chiuderli alla fine della richiesta? – RandomWebGuy

Problemi correlati