20100316

Binding Fluent NHibernate session to HttpContext

It is very useful and common practice to bind Fluent NHibernate session to HttpContext. Easiest way to do it is to create HttpModule.

public class ExampleSessionModule : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            context.BeginRequest += OpenSession;
            context.EndRequest += CloseSession; 
        }

        private void OpenSession(object sender, EventArgs e)
        {
            ExampleSessionProvider.Instance.OpenSession();            
        }
        
        private void CloseSession(object sender, EventArgs e)
        {
            ExampleSessionProvider.Instance.CloseSession();
        } 

        public void Dispose()
        {
            
        }
    }

The you just need a session provider.

public class ExampleSessionProvider
    {
        private const string SESION_KEY = "SESSION_KEY";

        private ExampleSessionProvider()
        {

        }

        private static ExampleSessionProvider instance;

        public static ExampleSessionProvider Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new ExampleSessionProvider();
                }
                return instance;
            }
        }

        private ISessionFactory sessionFactory;

        public void CreateSessionFactory()
        {
            sessionFactory = Fluently.Configure();                
                .ExposeConfiguration(BuildSchema)
                .BuildSessionFactory();
            // add more configuration options above !!!
        }

        public ISession GetSession()
        {
            if (HttpContext.Current != null)
            {
                return sessionFactory.GetCurrentSession();
            }           
            return null;
        }

        public ISession OpenSession()
        {
            ISession session = sessionFactory.OpenSession();
            ManagedWebSessionContext.Bind(HttpContext.Current, session);            
            return session;
        }

        public void CloseSession()
        {
            ISession session = ManagedWebSessionContext.Unbind(HttpContext.Current, sessionFactory);            
            if (session != null)
            {
                if (session.Transaction != null &&
                    session.Transaction.IsActive)
                {
                    session.Transaction.Rollback();
                }
                else
                {
                    session.Flush();
                }
                session.Close();
            }
        }

        private static void BuildSchema(Configuration config)
        {
            config.SetProperty("current_session_context_class", "managed_web");
        }
    }

And a bit of web.config configuration:
<system.web>
<httpModules>
<add name="ExampleSessionModule" type="Example.Session.ExampleSessionModule, Example" />
</httpModules>
</system.web>

OR (depending on IIS version)

<system.webServer>
<modules>
<add name="ExampleSessionModule" type="Example.Session.ExampleSessionModule, Example" />
</modules>
</system.webServer>

Last thing to do is to create session factory in Application Start event.

protected void Application_Start(Object sender, EventArgs e)
{
    ExampleSessionProvider.Instance.CreateSessionFactory();
}

No comments: