Aprendiendo Session-Per-Request con NHibernate; en solo 100 páginas

A menudo veo en el foro de NHibernate hispano que alguien pregunta como manejar la session de NHibernate en aplicaciones WEB, o algunas otras preguntas raras como si es necesario algún framework para manejar la session.

Sea ASP.NET o ASP.Net MVC el patrón que solemos usar es session-per-request. En este post voy a comentar como yo suelo hacer esto.

Las 50 primeras páginas las voy a dedicar pura y exclusivamente a la teoría:

Session y Transaction tienen igual ciclo de vida que un web request.

Recordar que NHibernate ya dispone de una forma de manejar sesiones de contexto, y la que vamos a usar es “managed_web”.  entonces lo único que tenemos que hacer en nuestro archivo de configuración de NHibernate es lo siguiente:

<property name="current_session_context_class">managed_web</property>

De esta forma le estamos diciendo a nhibernate que vamos a utilizar ese contexto. La particularidad de ese “manejador” de contexto es que guarda la session actual en un HttpContext.

Luego en el código lo único que tenemos que hacer es lo siguiente:

public class Global: System.Web.HttpApplication
{
    public static ISessionFactory SessionFactory 
                            = CreateSessionFactory();
    
    protected static ISessionFactory CreateSessionFactory()
    {
        return new Configuration()
            .Configure()
            .BuildSessionFactory();
    }
    
    
    protected void Global()
    {
        BeginRequest += (sender, args) => 
        {
                var session = Session.OpenSession()
                ManagedWebSessionContext.Bind(
                        HttpContext.Current,
                        session);
                session.BeginTransaction();

        };
        EndRequest += (sender, args) => 
        {
                ISession session = ManagedWebSessionContext.Unbind(
                                HttpContext.Current, SessionFactory);
                if (session != null)
                {
                    if (session.Transaction != null &&
                        session.Transaction.IsActive)
                    {
                        session.Transaction.Commit();
                    }
                    session.Close();
                }
        };
    }
}

Si la aplicación tiene mucho contenido que no necesita acceder a la persistencia, como páginas estáticas haría una pequeña modificación allí para que no inicie una transacción por cada request.

Como acceder a la Session desde nuestros repositorios o daos, es muy sencillo:

namespace SGF.Data.Impl.Repositories
{
    public class Dao<T> : IDao<T>
    {
        private readonly ISessionFactory _factory;

        public Dao(ISessionFactory factory)
        {
            _factory = factory;
        }

        protected ISession Session
        {
            get { return _factory.GetCurrentSession(); }
        }

        #region IDao<T> Members

        public T Get(object id)
        {
            return Session.Get<T>(id);
        }

        public T GetProxy(object id)
        {
            return Session.Load<T>(id);
        }

        public T Save(T entity)
        {
            Session.Save(entity);
            return entity;
        }

        // and so on..

    }
}

Nuestros DAO’s dependen de ISessionFactory, dado que en el constructor esperan un ISessionFactory. Casi nunca construyo un DAO manualmente siempre lo hace mi IoC container… Pero eso son 200 páginas más.


blog comments powered by Disqus
  • Categories

  • Archives