C# NHibernate如何避免会话已关闭

C# NHibernate如何避免会话已关闭,c#,nhibernate,fluent-nhibernate,nhibernate-configuration,C#,Nhibernate,Fluent Nhibernate,Nhibernate Configuration,在调用我的类中的第二个查询时,我无法理解为什么im getting会话关闭 首先,我调用方法getpolicydata() 我跑得很好 之后,我调用GetSkadeData() 它抛出了一个错误: DbFactory类如下所示 class DbFactory { private static Lazy<ISessionFactory> factory = new Lazy<ISessionFactory>(GetSessionFactory, System.Thr

在调用我的类中的第二个查询时,我无法理解为什么im getting会话关闭

首先,我调用方法getpolicydata() 我跑得很好 之后,我调用GetSkadeData() 它抛出了一个错误:

DbFactory类如下所示

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

    }

}
类DbFactory
{
private static Lazy factory=new Lazy(GetSessionFactory,System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
公共数据库工厂()
{
}
公共列表getpolicydata(){
使用(ISession session=OpenSession())
{
IList pols=session.Query().Where(p=>p.policyNumber==053126703.ToList();
返回pols.ToList();
}
}
公共列表getSkadeData()
{
使用(ISession session=OpenSession())
{
IList skader=session.Query().Where(p=>p.Postnr==“7700”).ToList();
返回skader.ToList();
}
}
私有静态ISession OpenSession()
{
返回factory.Value.GetCurrentSession();
}
私有静态ISessionFactory GetSessionFactory()
{
//NHibernate.Cfg.Configuration
var c=新配置();
//c、 Configure();
c、 数据库集成(db=>
{
db.ConnectionString=“服务器=\”本地主机\“数据库=测试数据库;集成安全性=SSPI”;
db.方言();
});
//c、 配置(“c:\XML.XML”);
ModelMapper maps=新的ModelMapper();
AddMapping();
AddMapping();
c、 AddMapping(maps.compileMappingForAllExplicitlyAddedIdentity());
c、 CurrentSessionContext();
//c、 Configure().Configure();
var sessionFac=c.BuildSessionFactory();
返回会话fac;
//返回sessionFac.GetCurrentSession();
}
}
当我从另一个类调用该方法时,我正在这样做

List<PoliceData> test = new List<PoliceData>();
List<SkadeData> skader = new List<SkadeData>();
DbFactory poli = new DbFactory();
test = poli.getPoliceData();
skader = poli.getSkadeData();
List test=newlist();
List skader=新列表();
DbFactory poli=新的DbFactory();
test=poli.getpolicydata();
skader=poli.getSkadeData();
我是否需要创建dbfactory的新实例,或者是否可以对两个不同的查询使用相同的会话。 如果Nhibernate只是混乱了一次,然后在需要的时候打开和关闭会话,那就太好了

一般来说(使用任何ORM工具),我们应该避免使用(OpenSession()){…}语句,并且不仅为单个操作,而且为完整的web请求或工作单元保持会话打开。检查文档:

大多数使用NHibernate的应用程序需要某种形式的“上下文”会话,其中给定会话在给定上下文的整个范围内有效。然而,在不同的应用程序中,上下文的定义通常是不同的;不同的语境定义了电流概念的不同范围

有关其合同的详细讨论,请参阅NHibernate.Context.iccurrentsessionContext接口的API文档。它定义了一个方法CurrentSession(),通过该方法实现负责跟踪当前上下文会话。开箱即用,NHibernate提供了此接口的几种实现:

  • NHibernate.Context.CallSessionContext-当前会话由CallContext跟踪。您有责任绑定和解除绑定ISession 实例,该实例具有类CurrentSessionContext的静态方法

  • NHibernate.Context.ThreadStaticSessionContext-当前会话存储在线程静态变量中。此上下文仅支持一个 会话工厂。您有责任绑定和解除绑定ISession 实例,该实例具有类CurrentSessionContext的静态方法

  • NHibernate.Context.WebSessionContext-将当前会话存储在HttpContext中。您有责任绑定和解除绑定ISession 实例,该实例具有类CurrentSessionContext的静态方法

  • NHibernate.Context.wcfoOperationSessionContext-当前会话由WCF OperationContext跟踪。您需要注册 WCF中的WcfStateExtension扩展。你有责任约束和保护自己 使用类的静态方法解除ISession实例的绑定 CurrentSessionContext

  • NHibernate.Context.ManagedWebSessionContext-当前会话由HttpContext跟踪。在NHibernate 4.0中删除- 应改用NHibernate.Context.WebSessionContext。你是 负责将ISession实例与静态 方法,它从不打开、刷新或关闭ISession 本身


您是否尝试使用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();
}
public List getSkadeData(ISession会话)
{
IList skader=session.Query().Where(p=>p.Postnr==“7700”).ToList();
返回skader.ToList();
}

可能有用

在我们进行此操作时,我强烈建议不要为整个HTTP请求打开
ISession
。如果您使用的是ASP.NET MVC,请在操作方法中打开一个会话(如果您的操作筛选器或诸如此类的操作不需要DB访问权限,请在更早的时候打开),并在操作方法完成后立即关闭。这样你就不会被懒散的负载、N+1选择和其他讨厌的东西咬到。阅读数据库,准备视图模型,关闭ISession,然后渲染视图。大家好,非常感谢,我今天下班回家后会立即调查此事。谢谢你们的回复