-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 
Author Message
 Post subject: Open DataReader error
PostPosted: Mon Mar 03, 2008 1:52 pm 
Newbie

Joined: Mon Mar 03, 2008 1:44 pm
Posts: 12
Location: Vancouver, BC
Hibernate version:1.2.0.GA

We have recently gone live with an application using NHibernate. I am experiencing a problem on the production server that I have not experienced on our dev server; I suspect the major difference is simply the number of users hitting the application at the same time.

The exception is: could not execute query
[ select staffmembe0_.StaffMemberID ... etc

The inner exception is: There is already an open DataReader associated with this Command which must be closed first.

Below is the query method and stack trace, followed by an NHibernateHelper utility class which handles opening and closing of the NHibernate sessions.

I believe that I am closing my sessions correctly, yes? Is there any other reason this error could be triggered?

1. My query method:
Code:
            string hqlQuery = "from StaffMember stm "
                + "left join fetch stm.DepartmentPosition dpo "
                + "left join fetch dpo.PositionType ptp "
                + "left join fetch dpo.Department dpt "
                + "left join fetch stm.Professional pro "
                + "left join fetch pro.Person per "
                + "where stm.UserName = :UserName";

            StaffMember staffMember = null;

            try
            {
                ISession session = NHibernateHelper.GetCurrentSession();

                staffMember = (StaffMember)session.CreateQuery(hqlQuery)
                                            .SetString("UserName", userName)
                                            .UniqueResult<StaffMember>();
            }
            catch (HibernateException hEx)
            {
                ExceptionManager.HandleException(this, hEx);
            }
            catch (Exception ex)
            {
                ExceptionManager.HandleException(this, ex);
            }
            finally
            {
                NHibernateHelper.CloseSession();
            }

2. Stack trace:
   at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes)
   at NHibernate.Hql.Classic.QueryTranslator.List(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters, IList results)
   at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters)
   at NHibernate.Impl.QueryImpl.List()
   at NHibernate.Impl.AbstractQueryImpl.UniqueResult[T]()
   at KnowledgeTech.Umby.Repository.NHibernateRepositories.StaffMemberRepositoryNHibernate.FindByUserName(String domainAndUserName)


3. NHibernateHelper class:

public class NHibernateHelper
{
        private static readonly ISessionFactory sessionFactory;
        private static ISession _currentSession;

        static NHibernateHelper()
        {
            sessionFactory = new Configuration().Configure().BuildSessionFactory();
        }

        public static ISession GetCurrentSession()
        {
            if (_currentSession == null || !_currentSession.IsOpen)
            {
                _currentSession = sessionFactory.OpenSession();
            }

            return _currentSession;
        }

        public static void CloseSession()
        {
            _currentSession.Close();
        }
}


Thanks,

David


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 2:01 pm 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
Does you application utilize multiple threads in that case you should make the ISession in your NHibernateHelper Threadstatic. If its a web application the ISession instance should be stored in HttpContext


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 2:15 pm 
Newbie

Joined: Mon Mar 03, 2008 1:44 pm
Posts: 12
Location: Vancouver, BC
This has been followed by 2 further errors in the last few minutes on the same method.

Any idea what could be causing this?

David

1. Exception: could not execute query
InnerException: possible non-threadsafe access to the session

StackTrace:
at NHibernate.Loader.Loader.DoList (same as previous post...)

2. Exception: There was a problem converting an IDataReader to NDataReader
InnerException: Invalid attempt to FieldCount when reader is closed.

Stack Trace:
StackTrace:
at NHibernate.Driver.NDataReader..ctor(IDataReader reader, Boolean isMidstream)
at NHibernate.Driver.NHybridDataReader.ReadIntoMemory()
at NHibernate.Impl.BatcherImpl.CheckReaders()
at NHibernate.Impl.BatcherImpl.ExecuteReader(IDbCommand cmd)
at NHibernate.Loader.Loader.GetResultSet(IDbCommand st, RowSelection selection, ISessionImplementor session)
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes)
at NHibernate.Hql.Classic.QueryTranslator.List(ISessionImplementor session, QueryParameters queryParameters)
at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters, IList results)
at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters)
at NHibernate.Impl.QueryImpl.List()
at NHibernate.Impl.AbstractQueryImpl.UniqueResult[T]()
at KnowledgeTech.Umby.Repository.NHibernateRepositories.StaffMemberRepositoryNHibernate.FindByUserName(String domainAndUserName)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 2:16 pm 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
It sounds very much like you are using the non-thread-safe ISession in multiple threads


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 2:22 pm 
Newbie

Joined: Mon Mar 03, 2008 1:44 pm
Posts: 12
Location: Vancouver, BC
jta wrote:
Does you application utilize multiple threads in that case you should make the ISession in your NHibernateHelper Threadstatic. If its a web application the ISession instance should be stored in HttpContext


It`s a web service (WCF) application, and I haven`t stored the ISession in HttpContext. Should that be done one-time in my web.config settings? Or should that be set programatically in my NHibernateHelper class?

Current web.config settings below.

David

Code:
  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      <property name="connection.connection_string">Data Source=localhost;Initial Catalog=CaseFileMgmtSys;Integrated Security=True</property>
      <mapping assembly="KnowledgeTech.Umby.Domain" />
    </session-factory>
  </hibernate-configuration>


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 2:32 pm 
Newbie

Joined: Mon Mar 03, 2008 1:44 pm
Posts: 12
Location: Vancouver, BC
If I modify my NHibernateHelper.GetCurrentSession() method as follows, would this resolve the issue?

David

Code:
         // the nhibernate session is a singleton to the http request
         HttpContext currentContext = HttpContext.Current;
       
         ISession session = currentContext.Items[KEY_NHIBERNATE_SESSION] as ISession;

         if (session == null)
         {
            session = CreateSession();
            currentContext.Items[KEY_NHIBERNATE_SESSION] = session;
         }

         return session;


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 2:50 pm 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
It looks right but no reason to reinvent the wheel, take a look here:

http://www.hibernate.org/363.html

or if you want (what i think is) a beautiful solution, look at the NHibernate Facility for the Windsor container


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 3:11 pm 
Newbie

Joined: Mon Mar 03, 2008 1:44 pm
Posts: 12
Location: Vancouver, BC
jta wrote:
It looks right but no reason to reinvent the wheel, take a look here:

http://www.hibernate.org/363.html

or if you want (what i think is) a beautiful solution, look at the NHibernate Facility for the Windsor container


Thanks jta, I`ll let you know how this goes.

David


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 4:10 pm 
Newbie

Joined: Mon Mar 03, 2008 1:44 pm
Posts: 12
Location: Vancouver, BC
Further exploration: there is no HttpContext at the scope of my repositories, because they are in a separate class library.

My application consists of an ASP.NET WCF web service, which is then addressing 3 separate class libraries:

* the service layer
* the repository (DAO) query layer
* the domain model

I could just as easily call the service layer from a Windows Form app as a web app, so it makes sense that I would not try to resolve this issue in the repository layer with HttpContext.

Therefore, it make sense to use the ThreadStatic attribute, yes?

Code:
public class NHibernateHelper
{
        private static readonly ISessionFactory sessionFactory;

        [ThreadStatic]
        private static ISession _currentSession;

        static NHibernateHelper()
        {
            sessionFactory = new Configuration().Configure().BuildSessionFactory();
        }

        public static ISession GetCurrentSession()
        {
            if (_currentSession == null || !_currentSession.IsOpen)
            {
                _currentSession = sessionFactory.OpenSession();
            }

            return _currentSession;
        }

        public static void CloseSession()
        {
            _currentSession.Close();
        }
}


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 4:17 pm 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
Dont use threadstatic in web applications.. You have no garantuess that it will work.

Instead you can access HttpContext no matter what using:

System.Web.HttpContext.Current

But you will have to check if its available, but this gives an ugly dependency for your SessionHandling code to depend on System.Web so again i would bring Castle Windsor and its NHibernate facility to your attention :)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 5:50 pm 
Newbie

Joined: Mon Mar 03, 2008 1:44 pm
Posts: 12
Location: Vancouver, BC
jta wrote:
Dont use threadstatic in web applications.. You have no garantuess that it will work.

Instead you can access HttpContext no matter what using:

System.Web.HttpContext.Current

But you will have to check if its available, but this gives an ugly dependency for your SessionHandling code to depend on System.Web so again i would bring Castle Windsor and its NHibernate facility to your attention :)


I`ve retested this a couple of times now; my repository layer class library, which is referenced by my ASP.NET web service, doesn`t recognize HttpContext.

I`ve reference System.Web in the class library, and have put the following test line of code:

HttpContext currentContext = HttpContext.Current;

in one of the methods whose point of origin is a method in the ASP.NET web service layer.

However, HttpContext.Current shows up consistently as null, which leads me to suspect that ASP.NET layer is not visible to the repository layer class library.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 03, 2008 6:05 pm 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
Take a look at managedWebContext as described here:
http://www.hibernate.org/hib_docs/nhibe ... cture.html in 2.3. Contextual Sessions

Perhabs look at the implementation in nhibernate source its located in Context\ManagedWebSessionContext.cs


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.