Skip to content

Instantly share code, notes, and snippets.

@oguzhaneren
Forked from anonymous/gist:852307
Last active December 28, 2015 05:49
Show Gist options
  • Save oguzhaneren/7452723 to your computer and use it in GitHub Desktop.
Save oguzhaneren/7452723 to your computer and use it in GitHub Desktop.
NHibernate Session Per Web Request
using System;
using System.Collections.Generic;
using System.Web;
using NHibernate;
using NHibernate.Context;
using NHibernate.Engine;
namespace WebHub.Infrastracture.SessionManagement
{
public class LazySessionContext : ICurrentSessionContext
{
private readonly ISessionFactoryImplementor factory;
private const string CurrentSessionContextKey = "NHibernateCurrentSession";
public LazySessionContext(ISessionFactoryImplementor factory)
{
this.factory = factory;
}
/// <summary>
/// Retrieve the current session for the session factory.
/// </summary>
/// <returns></returns>
public ISession CurrentSession()
{
Lazy<ISession> initializer;
var currentSessionFactoryMap = GetCurrentFactoryMap();
if(currentSessionFactoryMap == null ||
!currentSessionFactoryMap.TryGetValue(factory, out initializer))
{
return null;
}
return initializer.Value;
}
/// <summary>
/// Bind a new sessionInitializer to the context of the sessionFactory.
/// </summary>
/// <param name="sessionInitializer"></param>
/// <param name="sessionFactory"></param>
public static void Bind(Lazy<ISession> sessionInitializer, ISessionFactory sessionFactory)
{
var map = GetCurrentFactoryMap();
map[sessionFactory] = sessionInitializer;
}
/// <summary>
/// Unbind the current session of the session factory.
/// </summary>
/// <param name="sessionFactory"></param>
/// <returns></returns>
public static ISession UnBind(ISessionFactory sessionFactory)
{
var map = GetCurrentFactoryMap();
var sessionInitializer = map[sessionFactory];
map[sessionFactory] = null;
if(sessionInitializer == null || !sessionInitializer.IsValueCreated) return null;
return sessionInitializer.Value;
}
/// <summary>
/// Provides the CurrentMap of SessionFactories.
/// If there is no map create/store and return a new one.
/// </summary>
/// <returns></returns>
private static IDictionary<ISessionFactory, Lazy<ISession>> GetCurrentFactoryMap()
{
var currentFactoryMap = (IDictionary<ISessionFactory,Lazy<ISession>>)
HttpContext.Current.Items[CurrentSessionContextKey];
if(currentFactoryMap == null)
{
currentFactoryMap = new Dictionary<ISessionFactory, Lazy<ISession>>();
HttpContext.Current.Items[CurrentSessionContextKey] = currentFactoryMap;
}
return currentFactoryMap;
}
}
public interface ISessionFactoryProvider
{
IEnumerable<ISessionFactory> GetSessionFactories();
}
public class SessionFactoryProvider
{
public const string Key = "NHibernateSessionFactoryProvider";
}
public class NHibernateSessionModule : IHttpModule
{
private HttpApplication app;
private ISessionFactoryProvider sfp;
public void Init(HttpApplication context)
{
app = context;
sfp = (ISessionFactoryProvider) context.Application[SessionFactoryProvider.Key];
context.BeginRequest += ContextBeginRequest;
context.EndRequest += ContextEndRequest;
}
private void ContextBeginRequest(object sender, EventArgs e)
{
foreach (var sf in sfp.GetSessionFactories())
{
var localFactory = sf;
LazySessionContext.Bind(
new Lazy<ISession>(() => BeginSession(localFactory)),
sf);
}
}
private static ISession BeginSession(ISessionFactory sf)
{
var session = sf.OpenSession();
session.BeginTransaction();
return session;
}
private void ContextEndRequest(object sender, EventArgs e)
{
foreach (var sf in sfp.GetSessionFactories())
{
var session = LazySessionContext.UnBind(sf);
if (session == null) continue;
EndSession(session);
}
}
private static void EndSession(ISession session)
{
if(session.Transaction != null && session.Transaction.IsActive)
{
session.Transaction.Commit();
}
session.Dispose();
}
public void Dispose()
{
app.BeginRequest -= ContextBeginRequest;
app.EndRequest -= ContextEndRequest;
}
}
}
//Example of IWindsorInstaller:
public class NHibernateInstaller : IWindsorInstaller
{
#region IWindsorInstaller Members
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<ISessionFactory>()
.UsingFactoryMethod(k => BuildSessionFactory()));
container.Register(Component.For<NHibernateSessionModule>());
container.Register(Component.For<ISessionFactoryProvider>().AsFactory());
container.Register(Component.For<IEnumerable<ISessionFactory>>()
.UsingFactoryMethod(k => k.ResolveAll<ISessionFactory>()));
HttpContext.Current.Application[SessionFactoryProvider.Key]
= container.Resolve<ISessionFactoryProvider>();
}
#endregion
public ISessionFactory BuildSessionFactory() { ... }
}
//Example of dao
public class Dao<T> : IDao<T>
{
private readonly ISessionFactory sessionFactory;
public Dao(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
public void Save(T transient)
{
sessionFactory.GetCurrentSession().Save(transient);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment