From 2d81d541012da511eac7f6336ada84f931eee2b1 Mon Sep 17 00:00:00 2001 From: von Date: Sun, 9 Dec 2012 22:33:11 +0800 Subject: [PATCH] New class to enable NH session management in Web API --- .../WebApi/SessionPerRequestModule.cs | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 SharpLiteSrc/app/SharpLite.NHibernateProvider/WebApi/SessionPerRequestModule.cs diff --git a/SharpLiteSrc/app/SharpLite.NHibernateProvider/WebApi/SessionPerRequestModule.cs b/SharpLiteSrc/app/SharpLite.NHibernateProvider/WebApi/SessionPerRequestModule.cs new file mode 100644 index 0000000..96bca07 --- /dev/null +++ b/SharpLiteSrc/app/SharpLite.NHibernateProvider/WebApi/SessionPerRequestModule.cs @@ -0,0 +1,101 @@ +using System; +using System.Linq; +using System.Web; +using NHibernate; +using System.Collections.Generic; + +// This is needed for the DependencyResolver...wish they would've just used Common Service Locator! +using System.Net.Http; +using System.Web.Http; +using System.Web.Http.Controllers; +using System.Web.Http.Dependencies; +using System.Web.Http.Dispatcher; +using System.Web.Http.Services; + +using System.Web.Mvc; + + +namespace SharpLite.NHibernateProvider.WebApi +{ + /// + /// Taken from http://nhforge.org/blogs/nhibernate/archive/2011/03/03/effective-nhibernate-session-management-for-web-apps.aspx + /// + public class SessionPerRequestModule : IHttpModule + { + public void Init(HttpApplication context) { + context.BeginRequest += ContextBeginRequest; + context.EndRequest += ContextEndRequest; + context.Error += ContextError; + } + + private void ContextBeginRequest(object sender, EventArgs e) { + foreach (var sessionFactory in GetSessionFactories()) { + var localFactory = sessionFactory; + + LazySessionContext.Bind(new Lazy(() => BeginSession(localFactory)), sessionFactory); + } + } + + private static ISession BeginSession(ISessionFactory sessionFactory) { + var session = sessionFactory.OpenSession(); + session.BeginTransaction(); + return session; + } + + private void ContextEndRequest(object sender, EventArgs e) { + foreach (var sessionfactory in GetSessionFactories()) { + var session = LazySessionContext.UnBind(sessionfactory); + if (session == null) continue; + EndSession(session); + } + } + + private void ContextError(object sender, EventArgs e) { + foreach (var sessionfactory in GetSessionFactories()) { + var session = LazySessionContext.UnBind(sessionfactory); + if (session == null) continue; + EndSession(session, false); + } + } + + private static void EndSession(ISession session, bool commitTransaction = true) { + try { + if (session.Transaction != null && session.Transaction.IsActive) { + if (commitTransaction) { + try { + session.Transaction.Commit(); + } + catch { + session.Transaction.Rollback(); + throw; + } + } + else { + session.Transaction.Rollback(); + } + } + } + finally { + if (session.IsOpen) + session.Close(); + + session.Dispose(); + } + } + + public void Dispose() { } + + /// + /// Retrieves all ISessionFactory instances via IoC + /// + private IEnumerable GetSessionFactories() { + var sessionFactories = GlobalConfiguration.Configuration.DependencyResolver + .GetServices(typeof(ISessionFactory)).Cast(); + + if (sessionFactories == null || !sessionFactories.Any()) + throw new TypeLoadException("At least one ISessionFactory has not been registered with IoC"); + + return sessionFactories; + } + } +}