7

He planteado esta pregunta anteriormente, pero aún estoy luchando por encontrar un ejemplo que pueda entender (no me digan que mire el proyecto de arquitectura S # arp sin al menos algunas indicaciones).¿Cómo puedo implementar la sesión NHibernate por solicitud sin una dependencia en NHibernate?

Hasta ahora he logrado ignorancia de persistencia en mi proyecto web. Mis clases de repositorio (en mi proyecto de datos) tienen un ISession en el constructor:

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

En mi Global.asax que exponga la sesión actual y estoy creando y disponer sesión sobre BeginRequest y EndRequest (aquí es donde tengo el dependencia de 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(); 
     }; 
    } 

y finalmente mi registro StructureMap:

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

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

parecería que necesito mis propias implementaciones genéricas de ISession y ¿ISessionFactory que puedo usar en mi proyecto web e inyectar en mis repositorios?

Solo para aclarar: estoy usando NHibernate en mi capa de repositorio y quiero usar una solicitud de sesión por (http). Por lo tanto, estoy inyectando una ISession en mis constructores de repositorio (usando structuremap). Actualmente, para crear y eliminar las sesiones en cada solicitud, he tenido que hacer referencia a NHibernate desde mi proyecto web. Esta es la dependencia que me gustaría eliminar.

Gracias, Ben

+6

NHibernate es, según yo, no una mala dependencia. –

+0

Mi proyecto web habla con el repositorio y NHibernate es una dependencia del repositorio. Si no fuera por el hecho de que quería una sesión por solicitud, entonces podría simplemente abrir mis sesiones dentro de la capa de repositorio. Sin embargo, sí quiero una sesión por solicitud, pero no quiero que mi proyecto web esté vinculado a NHibernate. –

+2

Will Marcouiller: Sigue siendo una dependencia. Una dependencia es una dependencia. ¿Qué pasaría si Ben quisiera transferir su aplicación a CouchDB o MongoDB o usar una base de datos de objetos en memoria? –

Respuesta

3

¿Por qué no crear un IHttpModule y llevar a cabo su creación y disponer allí (probablemente en el Begin_Request y eventos End_Request), pero pone su IHttpModule dentro del proyecto que tiene su dependencia NHibernate . p.ej.

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 
     } 
    } 
} 

Quizás haya una mejor manera, estoy interesado en saber esto también, entonces ¿alguna sugerencia alternativa?

+0

esta es la ruta que comencé a bajar, pero como ustedes me interesa si hay alguna. es una forma mejor (más DI amigable) de hacer esto. –

+0

@Ben - Pero no es una mala mala dependencia, ya que no tendrá que referirse a estos objetos del suyo ni hacer referencia a ellos en su proyecto web. Todo lo que tienes que hacer es configurar eso en tu web.config. ¿Cuál es el problema?Si estuviera configurando su contenedor DI a través de XML, tendría que escribirlo también. – jfneis

+0

@jfneis: ¿tiene un ejemplo completo del uso de un HttpModule? Estoy particularmente interesado en cómo todavía puedo inyectar mi sesión en repositorios y si las transacciones se manejan de forma diferente. –

0

Gracias por la ayuda de todos hasta ahora. Un poco más de investigación me llevó al proyecto NHibernate Burrow.

Desde el FAQ proyecto (http://nhforge.org/wikis/burrow/faq.aspx):

madriguera es un middleware de peso ligero desarrollado para soportar aplicaciones .Net utilizando NHibernate (tal vez también conocida como NH en este artículo) como marco ORM. Usar Asp.net con NHibernate podría ser un desafío debido al hecho de que NHibernate es un entorno con estado, mientras que Asp.net es un marco sin estado. Burrow puede ayudar a resolver este conflicto al proporcionar una gestión de sesión/transacción inteligente y avanzada y otras facilidades.

Tuve que saltar unos aros para que funcione en mi proyecto. Dado que el lanzamiento actual usa una versión anterior de NHibernate, tuve que descargar el latest source del trunk, abrir en VS, agregar referencias a la última versión de NHibernate y volver a compilar (afortunadamente no hay errores).

He probado NHibernate Burrow de varias maneras.

1) Continuar inyectando ISession en mis repositorios

Para ello, he tenido que añadir referencias a NHibernate, NHibernate.Burrow y NHibernate.Burrow.WebUtil para mi proyecto MVC.

En web.config que tuvo que establecer Madriguera (ver http://nhforge.org/wikis/burrow/get-started.aspx) y luego en mi registro StructureMap añadir lo siguiente:

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

me gusta este enfoque, ya que significa mis repositorios (o controladores) no son junto con Burrow. Realmente no me gusta el hecho de que tengo que hacer referencia a estos tres ensamblajes en mi proyecto web, pero al menos pierdo el código para administrar la sesión; todo esto lo maneja Burrow.

2) El segundo enfoque sería establecer ISession en mis constructores repositorio de este modo:

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

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

Todavía puedo anular ISession hacer mis repositorios comprobable. Entonces tengo una dependencia directa de Burrow, pero tal vez esto no sea tan malo?

En el lado positivo, el único conjunto al que debo hacer referencia desde mi proyecto web es NHibernate.Burrow.WebUtils.

Interesado en ver cuál de las dos personas iría y por qué.

2

En mi opinión, debería abrazar la ISession y trabajar con ella directamente. El problema con muchas implementaciones de sesión por solicitud es que retrasan la realización de cambios en la base de datos hasta el final de la solicitud HTTP. Si la transacción falla, todo lo que puede hacer en ese punto es dirigir al usuario a una página de error genérica. Es mucho mejor administrar la transacción en la página para que pueda detectar y manejar los errores de manera más efectiva. Si toma esta ruta, entonces necesita acceder a la ISession o un contenedor para controlar la transacción.

Además, en algún momento su aplicación probablemente necesite usar propiedades o métodos expuestos por ISession, especialmente Merge y Load.

+0

¿Qué propondrías en lugar de la sesión por patrón de solicitud? ¿O está sugiriendo no abrir una sesión y una transacción al principio y luego cerrarlas al final de la solicitud? – RandomWebGuy

Cuestiones relacionadas