Question

For example. My session factory is located in MyDomain.SessionProvider class. Session can be open using ISession session = SessionProvider.Instance.OpenSession()

Step: SessionProvider.cs

public static SessionProvider Instance { get; private set; }
        private static ISessionFactory _SessionFactory;

        static SessionProvider()
        {
            var provider = new SessionProvider();
            provider.Initialize();
            Instance = provider;
        }

        private SessionProvider()
        {

        }

        private void Initialize()
        {
            string csStringName = "ConnectionString";
            var cfg = Fluently.Configure()
               //ommiting mapping and db conf.

                .ExposeConfiguration(c => c.SetProperty("current_session_context_class", "web"))
                .BuildConfiguration();
            _SessionFactory = cfg.BuildSessionFactory();

        }

        public ISession OpenSession()
        {
            return _SessionFactory.OpenSession();
        }

        public ISession GetCurrentSession()
        {
            return _SessionFactory.GetCurrentSession();
        }

Step: Global.asax.cs

public static ISessionFactory SessionFactory { get; private set; }

Application Start

SessionFactory = SessionProvider.Instance.OpenSession().SessionFactory;

App_BeginRequest

var session = SessionFactory.OpenSession();
CurrentSessionContext.Bind(session);   

EndRequest dispose session

var session = CurrentSessionContext.Unbind(SessionFactory);
session.Dispose();

Step3.HomeController I should be using current session like

var session = SessionProvider.Instance.GetCurrentSession();
using (var tran = session.BeginTransaction())
{
   //retrieve data from session
}

Now, with trying to retrieve data on my controller like desc. in Step3. I got error message that my session is closed. I tried to remove Application_EndRequest block inside global.asax cause my transaction is wrapped with session but with no success. Still same error.

Second/side question: is this pattern accepted widely, or it is better to wrapped inside custom attributes on mvc controllers. Thanks.

Updated: On my controller when try to instantiate current session in line

var session = SessionProvider.Instance.GetCurrentSession();

I'm getting following error:

**Connection = 'session.Connection' threw an exception of type 'NHibernate.HibernateException'**

**base {System.ApplicationException} = {"Session is closed"}**
Was it helpful?

Solution

Thanks @LeftyX

I solved this problem using TekPub video Mastering NHibernate with some customizations.

Global.asax

//Whenever the request from page comes in (single request for a page)
//open session and on request end close the session.

public static ISessionFactory SessionFactory =
   MyDomain.SessionProvider.CreateSessionFactory();

public MvcApplication() 
{
    this.BeginRequest += new EventHandler(MvcApplication_BeginRequest);
    this.EndRequest +=new EventHandler(MvcApplication_EndRequest);
}

private void MvcApplication_EndRequest(object sender, EventArgs e)
{
    CurrentSessionContext.Unbind(SessionFactory).Dispose();
}

private void MvcApplication_BeginRequest(object sender, EventArgs e)
{
    CurrentSessionContext.Bind(SessionFactory.OpenSession());
}

protected void Application_Start()
{
    SessionFactory.OpenSession();
}

and inside my controller

 var session = MvcApplication.SessionFactory.GetCurrentSession();
 {
     using (ITransaction tx = session.BeginTransaction())
      {... omitting retrieving data}
 }

OTHER TIPS

You can find a couple of simple and easy implementations here and here and find some code here.
I like Ayende's approach to keep everything simple and clean:

public class Global: System.Web.HttpApplication
{
    public static ISessionFactory SessionFactory = CreateSessionFactory();

    protected static ISessionFactory CreateSessionFactory()
    {
        return new Configuration()
            .Configure(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "hibernate.cfg.xml"))
            .BuildSessionFactory();
    }

    public static ISession CurrentSession
    {
        get{ return (ISession)HttpContext.Current.Items["current.session"]; }
        set { HttpContext.Current.Items["current.session"] = value; }
    }

    protected void Global()
    {
        BeginRequest += delegate
        {
            CurrentSession = SessionFactory.OpenSession();
        };
        EndRequest += delegate
        {
            if(CurrentSession != null)
                CurrentSession.Dispose();
        };
    }
}

In my projects I've decided to use a IoC container (StructureMap).
In case you're interested you can have a look here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top