3

I can not figure out why im getting session is closed when calling the second query in my class.

First i call the method, getPoliceData() I runs fine After that im calling GetSkadeData() and it throw the error:

the DbFactory class looks like this

class DbFactory
{
    private static Lazy<ISessionFactory> factory = new Lazy<ISessionFactory>(GetSessionFactory, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);

    public DbFactory()
    {



    }
    public List<PoliceData> getPoliceData()  {
    using (ISession session = OpenSession())
        {
            IList<PoliceData> pols = session.Query<PoliceData>().Where(p => p.policyNumber == 053126703).ToList();

         return pols.ToList();
        }

    }

    public List<SkadeData> getSkadeData()
    {
        using (ISession session = OpenSession())
        {
            IList<SkadeData> skader = session.Query<SkadeData>().Where(p => p.Postnr == "7700").ToList();

            return skader.ToList();
        }

    }



    private static ISession OpenSession()
    {
        return factory.Value.GetCurrentSession();
    }

    private static ISessionFactory GetSessionFactory()
    {
        //NHibernate.Cfg.Configuration
        var c = new Configuration();
        //c.Configure();
        c.DataBaseIntegration(db =>
        {
            db.ConnectionString = "Server=\"localhost\";database=testdb;Integrated Security=SSPI";
            db.Dialect<NHibernate.Dialect.MsSql2012Dialect>();

        });
        //c.Configure("c:\XML.xml");

        ModelMapper maps = new ModelMapper();
        maps.AddMapping<PoliceDataMap>();
        maps.AddMapping<SkadeDataMap>();
        c.AddMapping(maps.CompileMappingForAllExplicitlyAddedEntities());
        c.CurrentSessionContext<NHibernate.Context.ThreadLocalSessionContext>();
        //c.Configure().Configure();
        var sessionFac = c.BuildSessionFactory();
        return sessionFac;

        //return sessionFac.GetCurrentSession();

    }

}

When I call the method from another class I am doing this

List<PoliceData> test = new List<PoliceData>();
List<SkadeData> skader = new List<SkadeData>();
DbFactory poli = new DbFactory();
test = poli.getPoliceData();
skader = poli.getSkadeData();

Do I need to create a new instance of dbfactory or is it posible to use the same session for two different querys. It would be nice if the Nhibernate just got confured once and after that you just open and closed session when needed.

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
havmaage
  • 573
  • 7
  • 25

2 Answers2

3

In general (with any ORM tool) we should avoid using(OpenSession()) {...} statement and keep session open not only for single operation, but for a complete web request or unit of work. Check the doc:

2.3. Contextual Sessions

Most applications using NHibernate need some form of "contextual" sessions, where a given session is in effect throughout the scope of a given context. However, across applications the definition of what constitutes a context is typically different; and different contexts define different scopes to the notion of current.

...

See the API documentation for the NHibernate.Context.ICurrentSessionContext interface for a detailed discussion of its contract. It defines a single method, CurrentSession(), by which the implementation is responsible for tracking the current contextual session. Out-of-the-box, NHibernate comes with several implementations of this interface:

  • NHibernate.Context.CallSessionContext - current sessions are tracked by CallContext. You are responsible to bind and unbind an ISession instance with static methods of class CurrentSessionContext .

  • NHibernate.Context.ThreadStaticSessionContext - current session is stored in a thread-static variable. This context only supports one session factory. You are responsible to bind and unbind an ISession instance with static methods of class CurrentSessionContext.

  • NHibernate.Context.WebSessionContext - stores the current session in HttpContext. You are responsible to bind and unbind an ISession instance with static methods of class CurrentSessionContext.

  • NHibernate.Context.WcfOperationSessionContext - current sessions are tracked by WCF OperationContext. You need to register the WcfStateExtension extension in WCF. You are responsible to bind and unbind an ISession instance with static methods of class CurrentSessionContext.

  • NHibernate.Context.ManagedWebSessionContext - current sessions are tracked by HttpContext. Removed in NHibernate 4.0 - NHibernate.Context.WebSessionContext should be used instead. You are responsible to bind and unbind an ISession instance with static methods on this class, it never opens, flushes, or closes an ISession itself.

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • While we're at it, i _strongly_ discourage having `ISession` open for the entire HTTP request. If you're using ASP.NET MVC, open a session in an Action Method (or earlier if your Action Filters or whatnot require DB access) and close as soon as Action Method completes. This way you won't get bitten by lazy loads, N+1 selects and other nasty stuff. Read from the DB, prepare view models, _close `ISession`_ and only then render the view. – Anton Gogolev Oct 18 '15 at 11:16
0

Have you tried to create ISession using factory.value.OpenSession()?

If you want to share ISession based on your sample coding you can modify your method to take ISession then you can call it like this:

DbFactory poli = new DbFactory();
using (ISession session = poli.OpenSession()) {
  test = poli.getPoliceData(session);
  skader = poli.getSkadeData(session);
}

and your method now become:

public List<SkadeData> getSkadeData(ISession session)
{
  IList<SkadeData> skader = session.Query<SkadeData>().Where(p => p.Postnr == "7700").ToList();

  return skader.ToList();
}

It might work!

c.sokun
  • 1,622
  • 4
  • 25
  • 40
  • Hi guys thank you very much, i will look into this as soon as i am home from my daily job today.Thank you for the respons – havmaage Oct 19 '15 at 07:10