Re: [nhusers] nHibernate Session.Close does not close Oracle sessions

89 views
Skip to first unread message

Ramon Smits

unread,
Sep 28, 2012, 3:40:24 AM9/28/12
to nhu...@googlegroups.com


Please see the code snippets attached.

Please do not put code snippets in a word document. Better to just put these in the email it self or put them in text attachments or on a website like pastebin.com

-- Ramon

Joe Brockhaus

unread,
Sep 28, 2012, 9:46:17 AM9/28/12
to nhu...@googlegroups.com, Fluent NHibernate

public void DisposeCurrentUow()

       {
           GetUnitOfWork();
           daoFactory.Dispose(currentSessionUOW);
       }

       public UnitOfWork GetUnitOfWork
       {
           get { return (UnitOfWork)sessionHash[GetSession.GetHashCode()]; }
       }

Are these the same GetUnitOfWork() method?
Where is currentSessionUOW?

Where is sessionHash? Are you firing up multiple SessionFactories (and FluentNHibernateHelpers)? ie; more than one per instance of the worker process?

It seems like you might be muddying the boundary between HTTP sessions, IIS worker process, NH SessionFactory, and NH Session. And that might be resulting in NH Sessions/Factories being orphaned in the sessionHash (assuming that's stored in the HTTP Session). You might be able to confirm this by lowering the Session Timeout in IIS from its default (20min) to, say, 1 min. Ultimately that wouldn't solve the problem, but might help point to where the problem exists.

The SuppressFinalize also sticks out to me a bit. What prompted you to put this there? Was your factory showing up as disposed in new http sessions when you weren't expecting it to be? You shouldn't have to do this if you've architected it right, and aren't crossing those boundaries I mention above (for instance, storing an http session-agnostic object in each http session that makes a request, then subsequently disposing that object after each request). 

----
As for the word doc thing .. at least it wasn't .doc. I absolutely hate putting & seeing code in the group post/email because it seems to have an arbitrary fixed width and formatting is wrecked. The fact that .docx is an open format and respects the formatting is an added bonus. PasteBin is a good idea, but having everything I need in the email is convenient - especially in cases when my email is synced, but I don't have immediate access to data (which was the case for me when trying to help him and writing this up). Perhaps this is an 'official rule' of the group .. idk .. but it smells of an overzealous purist rant reminiscent of MS trolling, especially since you weren't helpful.. Personally, I think we're past that age of the internet.

------
Joe Brockhaus
joe.br...@gmail.com
------------


--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To post to this group, send email to nhu...@googlegroups.com.
To unsubscribe from this group, send email to nhusers+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/nhusers?hl=en.

JR

unread,
Oct 1, 2012, 9:45:38 PM10/1/12
to fluent-n...@googlegroups.com, nhu...@googlegroups.com
Thank you for getting back to me on this.

As per your suggestion, I have the original code snippets moved to this location - http://pastebin.com/Fzp7zs3k

Here are the requested details.

1.Are these the same GetUnitOfWork() method? - <JR>Yes.

2.Where is currentSessionUOW? - <JR>This is a private UnitofWork object in the BL(Biz Layer). This holds the session from the above GetUnitOfWork.

3.Where is sessionHash? - 
<JR> sessionHash is a Private hashtable in our GenricNHibernateRepository which hold the hashcode of a new nH session created from the below "ProcessSession".
Public abstract class GenericNHibernateRepository<T, IdT> : IGenericRepository<T, IdT>
    {
        private ISession session = null;
        private Type persistentType = typeof(T);
        private UnitOfWork persistentUnitOfWork = null;
        private Hashtable sessionHash = new Hashtable();

        /// <summary>
        /// GenericNHibernateRepository.
        /// </summary>
        /// <param name="nHibernateUnitOfWork">NHibernateUnitOfWork</param>
        protected GenericNHibernateRepository(UnitOfWork nHibernateUnitOfWork)
        {
            ProcessSession(nHibernateUnitOfWork);
        }

        /// <summary>
        /// ProcessSession.
        /// </summary>
        /// <param name="nHibernateUnitOfWork">NHibernateUnitOfWork</param>
        public void ProcessSession(UnitOfWork nHibernateUnitOfWork)
        {
           
            if (nHibernateUnitOfWork != null)
            {
                if (sessionHash[nHibernateUnitOfWork.Session.GetHashCode()] != null)
                {
                    nHibernateUnitOfWork = (UnitOfWork)sessionHash[nHibernateUnitOfWork.Session.GetHashCode()];
                }
            }

            if (nHibernateUnitOfWork == null)
            {
                FluentnHibernateHelper.Mapper = persistentType;
                Logger.WriteTraceStart(MethodBase.GetCurrentMethod(), "Creating new Unit of Work");
                nHibernateUnitOfWork = new UnitOfWork(FluentnHibernateHelper.SessionFactory);
            }
            sessionHash.Add(nHibernateUnitOfWork.Session.GetHashCode(), nHibernateUnitOfWork);
            session = nHibernateUnitOfWork.Session;
        }
...................................
.....................................
}

4. Are you firing up multiple SessionFactories (and FluentNHibernateHelpers)? ie; more than one per instance of the worker process?
<JR> We are not doing it explicitly from the code. But as part of couple of recent tests, I suspect that multiple Session Factories were created,while calling from concurrent threads. Could this be because that Session factory creation is not a thread safe operation?

Here is the code that we have for the session factory creation.
public UnitOfWork(ISessionFactory sessionFactory)
        {
            session = sessionFactory;
            Session = session.OpenSession();
            Session.FlushMode = FlushMode.Auto;
            if (Session.Transaction.IsActive)
            {
                transaction = Session.Transaction;
            }
            else
            {
                transaction = Session.BeginTransaction(IsolationLevel.Unspecified);
            }
        }
.........................
FluentNHibernateHelper:
public static class FluentnHibernateHelper
    {
        #region Page Level Constants

        private const string message = "Connection String Decryption Failed";
        private static ISessionFactory sessionFactory = null;
        private static string connection = string.Empty;

        #endregion

        public static ISessionFactory SessionFactory
        {
            get { return sessionFactory ?? (sessionFactory = CreateSessionFactory()); }
        }
        ..............
        private static ISessionFactory CreateSessionFactory()
        {
            NHibernate.Cfg.Configuration connection = Fluently.Configure().Database                                                      (OracleDataClientConfiguration.Oracle10.ConnectionString(ConnectionString)
                .UseReflectionOptimizer())
                .Mappings(m =>
                {
                    m.FluentMappings.Add<Map1>();
                    m.FluentMappings.Add<Map2>();                   
                     ...............
                }).BuildConfiguration();
            return connection.BuildSessionFactory();           
        }

        public static ISession OpenSession()
        {
            if (SessionFactory.GetCurrentSession().IsOpen)
                SessionFactory.GetCurrentSession().Close();
            return SessionFactory.OpenSession();
        }
    }
}

Thanks,
JR.
Reply all
Reply to author
Forward
0 new messages