1

We're using nhibernate in and asp.net MVC application.

We are implementing the Session per Request pattern, via a httpModule.

It looks pretty straight forward, but when we run with NHibernate Profiler, it clearly shows that the sessions are never getting closed.

the pattern seems straight forward...but I don't understand why the sessions are never closing.

here's the code i think is important.

set up the event handler:

    context.EndRequest += new EventHandler(this.context_EndRequest);

in the handler dispose the Session

private void context_EndRequest(object sender, EventArgs e)
        {
            netLogHdl.ArchDebug("NHibernateHttpModule.context_EndRequest() ");

            Dispose(0);// we are hitting 2 dbs and thus keep one session for each.
            Dispose(1);

            HttpContextBuildPolicy.DisposeAndClearAll();
        }


private void Dispose(int sessionIndex)
        {
            netLogHdl.ArchStart("NHibernateHttpModule.Dispose", "int sessionIndex=\" + sessionIndex + \")");

            try
            {
                //close the DB session
                string sessManagerName = "";
                string jcdcManager = "JCDC Manager";
                string spamisManager = "Spamis Manager";

                if (sessionIndex == 0)
                    sessManagerName = jcdcManager;
                else
                {
                    sessManagerName = spamisManager;
                }


                ISession oneSession = sessionPerDB[sessionIndex];
                if (oneSession != null)
                {
                    if (sessManagerName == jcdcManager) netLogHdl.ArchDebug(sessManagerName + " oneSession is NOT null");

                    if (oneSession.IsOpen)
                    {
                        // Don't flush - all saves should use transactions and calling Commit does the flush.
                        if (sessManagerName == jcdcManager) netLogHdl.ArchDebug(sessManagerName + " Closing the session");

                        //This will overrite it with the exact same session, if they don't match something weird is going on - EWB
                        oneSession = CurrentSessionContext.Unbind(factoryPerDB[sessionIndex]);
                        oneSession.Close();
                    }
                    else
                    {
                        if (sessManagerName == jcdcManager) netLogHdl.ArchDebug(sessManagerName + " Session is NOT open");
                    }

                    //if ( sessManagerName == jcdcManager ) netLogHdl.ArchDebug( sessManagerName + " Session got Dispose()-ing" );
                    //oneSession.Dispose();
                }
                else
                {
                    if (sessManagerName == jcdcManager) netLogHdl.ArchDebug(sessManagerName + " Session is NULL");
                }

                sessionPerDB[sessionIndex] = null;

            }
            catch (Exception)
            {

                throw;
            }


            netLogHdl.ArchEnd();
        }

Can anyone point me in the right direction? What shoud I look at, is the pattern not implemented correclty?

I'm flummoxed

Thanks!

E-

Eric Brown - Cal
  • 14,135
  • 12
  • 58
  • 97
  • In a comment in the above code, it says "Don't flush - all saves should use transactions and calling Commit does the flush. ", but the code is neither flushing nor using transactions. I think thats a problem. – Mahesh Velaga Dec 02 '09 at 19:39
  • Transaction are not same as session, he is probably handling it outside of the http module, just like I am. It is Session-Per-Request, not Transaction-Per-Request. – epitka Dec 02 '09 at 20:07
  • Yes transactions are being commited outside of this layer. I did jsut add a flush, right before the close incase a session was'nt using a transaction for some reason (ie a fetch) – Eric Brown - Cal Dec 02 '09 at 20:58

2 Answers2

1

You should call dispose and not disconnect or close. System.IDisposable implementing objects should always be disposed by calling the dispose method, or by a using block.

Paco
  • 8,335
  • 3
  • 30
  • 41
  • I am now doing a belt and suspenders approach oneSession = CurrentSessionContext.Unbind( factoryPerDB[ sessionIndex ] ); oneSession.Flush(); oneSession.Close(); oneSession.Dispose(); No joy, I still have eternal sessions. – Eric Brown - Cal Dec 02 '09 at 21:06
  • Than the errror is somewhere in the parts of the code I don't know about. – Paco Dec 02 '09 at 22:08
0

You also might want to have a look at the code on Ben Day's blog post about session management.

John Rayner
  • 3,485
  • 21
  • 13