2010-05-08 21 views

Respuesta

18

No estoy demasiado familiarizado con la forma en que deben manejarse las sesiones de NHibernate. Dicho esto, Autofac tiene un excelente manejo de por vida de instancias (scoping y deterministic disposal). Algunos recursos relacionados son this article y this question. Como estás en ASP.Net MVC land, asegúrate de consultar también the MVC integration stuff.

Para ilustrar este punto, he aquí una muestra rápida de cómo se puede utilizar delegados de fábrica autofac y la Owned genérica para obtener el control total de instancia de duración:

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 instalación de contenedores para conseguir que esto funcione es bastante sencillo. Tenga en cuenta que no tenemos que hacer nada para obtener los Func<> y Owned<> tipos, éstos se ponen a disposición automáticamente por Autofac:

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

Actualización: mi razonamiento aquí es que, de acuerdo con this NHibernate tutorial, la vida útil de la instancia de la sesión debe ser la de la "unidad de trabajo". Por lo tanto, necesitamos alguna forma de controlar tanto cuándo se crea la instancia de sesión como cuándo se elimina la sesión.

Con Autofac obtenemos este control mediante la solicitud de una Func<> en lugar del tipo directamente. No usar Func<> requeriría que la instancia de sesión se cree por adelantado antes de que se cree la instancia del controlador.

A continuación, el valor predeterminado en Autofac es que las instancias tienen la vida útil de su contenedor. Como sabemos que necesitamos el poder de disponer de esta instancia tan pronto como se realice la unidad de trabajo, solicitamos una instancia de Owned. La eliminación de la instancia propia en este caso eliminará inmediatamente la sesión subyacente.

+1

Hmm ... Me gustaría que la gente diera algunas críticas constructivas cuando votan negativamente. –

+0

¡Yo también! :) Gracias por su respuesta - Estoy echando un vistazo a sus sugerencias – UpTheCreek

+0

Hola, entiendo todo aquí, aparte de Func > - ¿Por qué usar esto? ¿Por qué no solo inyectar en la ISession estándar? No estoy seguro de entender realmente lo que hace el Func/Owned, pero de acuerdo con la documentación de autofac, si lo usa, ¿tiene que deshacerse del objeto manualmente? Un componente que obtiene referencias del propietario es responsable de llamar al propietario . Deséchelo cuando la instancia ya no sea necesaria. Es un error no limpiar las instancias de propiedad. http://code.google.com/p/autofac/wiki/NewInV2 – UpTheCreek

0

Editar: Parece que Autofac y probablemente otros contenedores pueden abarcar la vida útil correctamente. Si ese es el caso, ve por ello.

No es una buena idea utilizar su contenedor IoC para administrar sesiones directamente. La duración de su sesión debe corresponder a su unidad de trabajo (límite de transacción). En el caso de una aplicación web, esa debería ser la duración de una solicitud web.

La manera más común de conseguir esto es con un HttpModule que tanto crea la sesión y comienza su transacción cuando una solicitud comienza, entonces comete cuando la petición ha terminado. Haría que HttpModule registre la sesión en la colección HttpContext.Items.

En su contenedor IoC, podría registrar algo así como HttpContextSessionLocator contra ISessionLocator.

Debo mencionar que el manejo de errores genéricos debe localizar la sesión actual y deshacer la transacción automáticamente, o podría terminar cometiendo la mitad de una unidad de trabajo.

+4

* ¿Por qué * no es esa una buena idea? –

+1

Estoy de acuerdo con James en esto, inyecto una unidad de fábrica de trabajo en mis controladores (asp.net mvc) y creo una unidad de trabajo desde el interior del controlador cuando sea necesario. La fábrica es solo una clase contenedora (localizador de servicios) alrededor del contenedor IoC (Mapa de estructura) – AwkwardCoder

+0

@AWC: eso es exactamente lo que yo también haría.La cosa es que el contenedor Autofac te da las cosas de fábrica OOTB. –

Cuestiones relacionadas