NHibernate会议-什么';windows应用程序中处理会话的常用方法是什么?

NHibernate会议-什么';windows应用程序中处理会话的常用方法是什么?,nhibernate,Nhibernate,我刚刚开始使用NHibernate,我有一些问题不确定如何正确解决 我开始创建一个包含CUD和几个搜索方法的通用存储库。在DB操作期间,这些方法中的每一个都会打开一个单独的会话(以及必要时的事务)。这样做的问题(据我所知)是我不能利用相关集合/对象的延迟加载 由于在fluent映射中几乎每个实体关系都有。而不是.LazyLoad(),因此当我请求一个给定类型的所有实体的列表时,它会导致整个数据库被加载 如果我错了,请纠正我,因为我对NHibernate还是一个完全的新手:) 为了避免这种情况,最

我刚刚开始使用NHibernate,我有一些问题不确定如何正确解决

我开始创建一个包含CUD和几个搜索方法的通用存储库。在DB操作期间,这些方法中的每一个都会打开一个单独的会话(以及必要时的事务)。这样做的问题(据我所知)是我不能利用相关集合/对象的延迟加载

由于在fluent映射中几乎每个实体关系都有
。而不是.LazyLoad()
,因此当我请求一个给定类型的所有实体的列表时,它会导致整个数据库被加载

如果我错了,请纠正我,因为我对NHibernate还是一个完全的新手:)

为了避免这种情况,最常见的做法是什么?有一个全局静态会话在程序运行时保持活动状态,或者我应该怎么做


一些存储库代码:

public T GetById(int id)
{
    using (var session = NHibernateHelper.OpenSession())
    {
        return session.Get<T>(id);
    }
}

您的问题实际上归结为对象缓存和重用。如果您从一个会话加载一个Foo对象,那么您是否可以保留它,然后在稍后的时间点延迟加载它的Bar属性

每个ISession实例都被设计为表示一个工作单元,并带有一个一级缓存,允许您在该工作单元内多次检索对象,但只命中一个数据库。它不是线程安全的,绝对不应该在WinForms应用程序中用作静态对象

如果要在释放加载对象的会话时使用该对象,则需要使用session.SaveOrUpdate(对象)或session.Update(对象)将其与新会话关联

您可以在中找到所有这些解释

如果这看起来效率很低,那么请研究第二级缓存。这是在ISessionFactory级别提供的—您的会话工厂可以是静态的,如果启用二级缓存,这将有效地为您的大部分数据构建内存缓存。二级缓存仅适用于没有底层服务更新数据的情况——如果所有数据库更新都通过NHibernate进行,则是安全的

根据发布的代码进行编辑

您的会话使用处于错误的级别-您将其用于单个数据库get,而不是工作单元。在这种情况下,您的
GetById
方法应该接受它所使用的会话,并且会话实例应该在更高级别上进行管理。或者,如果您愿意,您的
PersonRepository
类应该管理会话,并且您应该为每个工作单元实例化和处理这种类型的对象

public T GetById(int id)
{
    return m_session.Get<T>(id);
}

using (var repository = new PersonRepository())
{
    var person = repository.GetById(1);
    var contactInfo = person.ContactInfo;
} // make sure the repository Dispose method disposes the session.
public T GetById(int-id)
{
返回m_session.Get(id);
}
使用(var repository=newpersonrepository())
{
var person=repository.GetById(1);
var contactInfo=person.contactInfo;
}//确保repository Dispose方法处理会话。

您收到的错误消息是因为不再有用于延迟加载集合的会话—您已经处理了它。

您的问题实际上归结为对象缓存和重用。如果您从一个会话加载一个Foo对象,那么您是否可以保留它,然后在稍后的时间点延迟加载它的Bar属性

每个ISession实例都被设计为表示一个工作单元,并带有一个一级缓存,允许您在该工作单元内多次检索对象,但只命中一个数据库。它不是线程安全的,绝对不应该在WinForms应用程序中用作静态对象

如果要在释放加载对象的会话时使用该对象,则需要使用session.SaveOrUpdate(对象)或session.Update(对象)将其与新会话关联

您可以在中找到所有这些解释

如果这看起来效率很低,那么请研究第二级缓存。这是在ISessionFactory级别提供的—您的会话工厂可以是静态的,如果启用二级缓存,这将有效地为您的大部分数据构建内存缓存。二级缓存仅适用于没有底层服务更新数据的情况——如果所有数据库更新都通过NHibernate进行,则是安全的

根据发布的代码进行编辑

您的会话使用处于错误的级别-您将其用于单个数据库get,而不是工作单元。在这种情况下,您的
GetById
方法应该接受它所使用的会话,并且会话实例应该在更高级别上进行管理。或者,如果您愿意,您的
PersonRepository
类应该管理会话,并且您应该为每个工作单元实例化和处理这种类型的对象

public T GetById(int id)
{
    return m_session.Get<T>(id);
}

using (var repository = new PersonRepository())
{
    var person = repository.GetById(1);
    var contactInfo = person.ContactInfo;
} // make sure the repository Dispose method disposes the session.
public T GetById(int-id)
{
返回m_session.Get(id);
}
使用(var repository=newpersonrepository())
{
var person=repository.GetById(1);
var contactInfo=person.contactInfo;
}//确保repository Dispose方法处理会话。

您收到的错误消息是因为不再有用于延迟加载集合的会话-您已经处理了它。

谢谢您的回答。我已经阅读了文档中的章节,但我仍然不太明白你在第二句话中的意思。你的意思是,如果我需要访问延迟加载的属性,我必须保留会话吗?我会在问题中添加一些我的存储库代码。当然-在问题中添加一些上下文,我会在回答中更具体地解决它。很好,非常感谢+1我将重构我的存储库:)我的理解是会话/db内容应该“分层”远离实际应用程序,因此如果我另外将其从存储库中删除,我会将其放置在哪里?顺便问一下,多个存储库呢?如果他们中的一个开了一个会,如果我需要手术,会不会导致问题