NHibernate如何避免session被关闭

NHibernate how to avoid session is closed

我不明白为什么我在 class 中调用第二个查询时关闭会话。

首先我调用方法 getPoliceData() 我跑得很好 之后我打电话给 GetSkadeData() 并抛出错误:

DbFactory class 看起来像这样

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();

    }

}

当我从另一个 class 调用方法时,我正在这样做

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

我是否需要创建一个新的 dbfactory 实例,或者是否可以对两个不同的查询使用相同的会话。 如果 Nhibernate 只需配置一次,然后您只需在需要时打开和关闭会话,那就太好了。

通常(使用任何 ORM 工具) 我们应该避免 using(OpenSession()) {...} 语句并保持会话打开,不仅针对单个操作,而且针对完整的 Web 请求或单元工作的。检查文档:

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.

您是否尝试过使用 factory.value.OpenSession() 创建 ISession?

如果您想根据您的示例代码共享 ISession,您可以修改您的方法以获取 ISession,然后您可以这样调用它:

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

你的方法现在变成了:

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

  return skader.ToList();
}

可能有用!