-
-
Save oguzhaneren/7452723 to your computer and use it in GitHub Desktop.
NHibernate Session Per Web Request
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
http://nhforge.org/blogs/nhibernate/archive/2011/03/03/effective-nhibernate-session-management-for-web-apps.aspx