Hi all,

I've been trying to come up with/find a 'best practice' route for NHib 
session management in ASP.Net WebForms.  I'm unable to use IoC containers 
etc due to architectural features of the code (it's a fixed framework we 
use internally).  What I'm looking for is some pointers on the solution 
I've come up with, as I'm sure it could be improved.

Keeping it simple, I'm trying to achieve session-per-request with no 
requirement for transactions.  The code below has an overall 'wrapping' 
transaction because I found if I did a delete then immediately re-loaded 
the list objects to the page in the same cycle, the deleted object would 
're-appear', even though I'd just deleted it (object disappears if I do a 
page refresh).  Not entirely sure why this is if I'm honest!  Do I need a 
Transaction/is it best practice?

Overall code is (the extension stuff is because I'm using IIS6 and found it 
begins/ends even when loading images etc):

        protected void Application_BeginRequest(object sender, EventArgs 
args)
        {
            HttpContext context = this.Context;
            string filePath = context.Request.FilePath;
            string fileExtension = 
VirtualPathUtility.GetExtension(filePath);
            if (fileExtension.Equals(".aspx") || 
fileExtension.Equals(".ashx"))
            {
                SessionFactoryManager.Instance.BeginTransaction();
            }
        }

        protected void Application_EndRequest(object sender, EventArgs args)
        {
            HttpContext context = this.Context;
            string filePath = context.Request.FilePath;
            string fileExtension = 
VirtualPathUtility.GetExtension(filePath);
            if (fileExtension.Equals(".aspx") || 
fileExtension.Equals(".ashx"))
            {
                SessionFactoryManager.Instance.CommitTransaction();
                SessionFactoryManager.Instance.CloseSession();
            }
        }

The session manager is a singleton and the interesting bits are:

        public ISession GetSession()
        {
            ISession session = ContextSession;

            if (session == null)
            {
                session = sessionFactory.OpenSession();
                session.FlushMode = FlushMode.Commit;

                ContextSession = session;
            }

            //Check.Ensure(session != null, "session was null");

            return session;
        }

        public void BeginTransaction()
        {
            ITransaction transaction = ContextTransaction;

            if (transaction == null)
            {
                transaction = GetSession().BeginTransaction();
                ContextTransaction = transaction;
            }
        }

        public void CommitTransaction()
        {
            ITransaction transaction = ContextTransaction;

            try
            {
                if (HasOpenTransaction())
                {
                    transaction.Commit();
                    ContextTransaction = null;
                }
            }
            catch (HibernateException)
            {
                RollbackTransaction();
                throw;
            }
        }

        /// <summary>
        /// If within a web context, this uses <see cref="HttpContext" /> 
instead of the WinForms 
        /// specific <see cref="CallContext" />.  Discussion concerning 
this found at 
        /// http://forum.springframework.net/showthread.php?t=572.
        /// </summary>
        private ITransaction ContextTransaction
        {
            get
            {
                if (IsInWebContext())
                {
                    return 
(ITransaction)HttpContext.Current.Items[TRANSACTION_KEY];
                }
                else
                {
                    return 
(ITransaction)CallContext.GetData(TRANSACTION_KEY);
                }
            }
            set
            {
                if (IsInWebContext())
                {
                    HttpContext.Current.Items[TRANSACTION_KEY] = value;
                }
                else
                {
                    CallContext.SetData(TRANSACTION_KEY, value);
                }
            }
        }

        /// <summary>
        /// If within a web context, this uses <see cref="HttpContext" /> 
instead of the WinForms 
        /// specific <see cref="CallContext" />.  Discussion concerning 
this found at 
        /// http://forum.springframework.net/showthread.php?t=572.
        /// </summary>
        private ISession ContextSession
        {
            get
            {
                if (IsInWebContext())
                {
                    return (ISession)HttpContext.Current.Items[SESSION_KEY];
                }
                else
                {
                    return (ISession)CallContext.GetData(SESSION_KEY);
                }
            }
            set
            {
                if (IsInWebContext())
                {
                    HttpContext.Current.Items[SESSION_KEY] = value;
                }
                else
                {
                    CallContext.SetData(SESSION_KEY, value);
                }
            }
        }

        private bool IsInWebContext()
        {
            return HttpContext.Current != null;
        }

Thanks for any thoughts on the above, as I've been finding it really hard 
to track down current information regarding NHibernate and WebForms without 
the use of IoC frameworks to manage sessions, etc.

Thanks,

Paul

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/nhusers/-/HVUlidE0dQQJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en.

Reply via email to