NHibernate Context Sessions in ASP.NET MVC

I want to use NHibernate contextual sessions in my ASP.NET MVC 2 application, but it’s hard for me to find recommendations on how to do this correctly.

I'm interested in session per request.

+6
c # asp.net-mvc asp.net-mvc-2
source share
3 answers

Please let me know if I am doing this correctly. Here is what I came up with:

Global.asax

public class MvcApplication : NinjectHttpApplication { public MvcApplication() { NHibernateProfiler.Initialize(); EndRequest += delegate { NHibernateHelper.EndContextSession(Kernel.Get<ISessionFactory>()); }; } public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.IgnoreRoute("favicon.ico"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); } protected override void OnApplicationStarted() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); } protected override IKernel CreateKernel() { StandardKernel kernel = new StandardKernel(); kernel.Load(AppDomain.CurrentDomain.GetAssemblies()); return kernel; } } 

NHibernateHelper

 public class NHibernateHelper { public static ISessionFactory CreateSessionFactory() { var nhConfig = new Configuration(); nhConfig.Configure(); return Fluently.Configure(nhConfig) .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Reservation>() .Conventions.Add(ForeignKey.EndsWith("Id"))) #if DEBUG .ExposeConfiguration(cfg => { new SchemaExport(cfg) .SetOutputFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "schema.sql")) .Create(true, false); }) #endif .BuildSessionFactory(); } public static ISession GetSession(ISessionFactory sessionFactory) { ISession session; if (CurrentSessionContext.HasBind(sessionFactory)) { session = sessionFactory.GetCurrentSession(); } else { session = sessionFactory.OpenSession(); CurrentSessionContext.Bind(session); } return session; } public static void EndContextSession(ISessionFactory sessionFactory) { var session = CurrentSessionContext.Unbind(sessionFactory); if (session != null && session.IsOpen) { try { if (session.Transaction != null && session.Transaction.IsActive) { // an unhandled exception has occurred and no db commit should be made session.Transaction.Rollback(); } } finally { session.Dispose(); } } } } 

NHibernateModule

 public class NHibernateModule : NinjectModule { public override void Load() { Bind<ISessionFactory>().ToMethod(x => NHibernateHelper.CreateSessionFactory()).InSingletonScope(); Bind<ISession>().ToMethod(x => NHibernateHelper.GetSession(Kernel.Get<ISessionFactory>())); } } 
+1
source share

We do a little different than bigglesby, and I do not say that he is mistaken or that our perfection.

In global.asax, we have when starting the application:

 ... protected void Application_Start() { ISessionFactory sf = DataRepository .CreateSessionFactory( ConfigurationManager .ConnectionStrings["conn_string"] .ConnectionString ); //use windsor castle to inject the session ControllerBuilder .Current .SetControllerFactory(new WindsorControllerFactory(sf)); } ... 

We have our DataRepository: NOTE: (this is not a repository - my design error: a bad name - it looks more like your NHibernateHelper, I suppose it's more like some kind of NH configuration shell ...)

 .... public static ISessionFactory CreateSessionFactory(string connectionString) { if (_sessionFactory == null){ _sessionFactory = Fluently.Configure() .Database(MsSqlConfiguration ... ... //custom configuration settings ... cfg.SetListener(ListenerType.PostInsert, new AuditListener()); }) .BuildSessionFactory(); } return _sessionFactory; } .... 

The thing with a factory session is that you do not want to generate / build one for each request. The DataRepository acts like a singleton, ensuring that the factory session is created only once, and this starts when the application starts. In our base controller, we enter either a session or sessionfactory into our controllers (some controllers do not require a database connection, so they get from the base controller without a database) using WindosrCastle. Our WindsorControllerFactory we have:

 ... //constructor public WindsorControllerFactory(ISessessionFactory) { Initialize(); // Set the session Factory for NHibernate _container.Register( Component.For<ISessionFactory>() .UsingFactoryMethod( () => sessionFactory) .LifeStyle .Transient ); } private void Initialize() { _container = new WindsorContainer( new XmlInterpreter( new ConfigResource("castle") ) ); _container.AddFacility<FactorySupportFacility>(); // Also register all the controller types as transient var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where typeof(IController).IsAssignableFrom(t) select t; foreach (var t in controllerTypes) { _container.AddComponentLifeStyle(t.FullName, t, LifestyleType.Transient); } } .... 

With this setting, each request generates an NHibernate session, and with our design we can also have controllers that do not generate sessions. And this is currently how it works for us.

May I also say that I found NHProf very useful when trying to configure or debug the problem we had.

+1
source share

http://www.sharparchitecture.net

You can learn the implementation from the wiki and sources there, as well as from here . A bit more information about S # arp here , including an explanation of session management.

-one
source share

All Articles