Nhibernate 会话断开连接时延迟加载失败

Nhibernate 会话断开连接时延迟加载失败,nhibernate,Nhibernate,我们使用一个只读会话,一旦从数据库检索到数据,就立即断开该会话。检索到的数据通常具有尚未初始化的延迟加载属性 当我们尝试访问属性时,会引发以下异常: NHibernate.LazyInitializationException异常 初始化[NHibernateTest.AppUser16]-未能延迟初始化角色集合:NHibernateTest.AppUser.Permissions,会话已断开连接 拦截器是否有办法自动检测应用程序正在尝试访问未初始化的属性,以便拦截器能够在工作单元完成后快速打开

我们使用一个只读会话,一旦从数据库检索到数据,就立即断开该会话。检索到的数据通常具有尚未初始化的延迟加载属性

当我们尝试访问属性时,会引发以下异常:

NHibernate.LazyInitializationException异常

初始化[NHibernateTest.AppUser16]-未能延迟初始化角色集合:NHibernateTest.AppUser.Permissions,会话已断开连接

拦截器是否有办法自动检测应用程序正在尝试访问未初始化的属性,以便拦截器能够在工作单元完成后快速打开并关闭连接


一次获取所有内容将使懒惰的使用无效。

没有有效的方法可以做到这一点。这样做的目的是让会话保持打开状态,直到您完成会话。每个工作单元应该有一节课。会话实际上是一种工作单元


在一个查询中获取所需的所有内容比在多个查询中获取所需的所有内容更有效,因此我不同意您的上一句话。惰性加载对像我这样的懒惰程序员很有用,但它永远不会比急切加载更有效。延迟加载可以为您节省一些编程时间,但您仍然需要注意执行的查询太多选择N+1

关于您的查询计数问题。。。您可以通过在持久化单元中使用批处理加载来减轻这种影响,这样,当您访问父实例的子实例时,NHibernate可以为所有当前已知的父实例获取多达``BatchSize子对象。我让您访问文档以了解更多有关这方面的信息。此外,在大多数情况下,如果不使用父实体的懒惰子实体,则平均而言,懒惰加载比急切加载更有效。它最终高度依赖于用例。@Romain Muller:1。批处理可用于多个性能优化,其中select n+1是其中之一。另一个是分页,我用它来做更多的事情,但是批处理并不能阻止每一个select n+1,它只会将select n+1转换成select n/b+1。2.不加载与懒惰和渴望加载是不同的。我的意思不是在映射中使用eager,我的意思是在查询中使用eager。@Paco,我并没有真正讨论是否延迟加载。。。我已经决定去做了。我的数据访问层给了我一个对象,在10次中有7次,我只是按原样使用。在10次中的3次中,它需要后期获取一些惰性属性。我接受性能瓶颈,并且我知道N+1。在我看来,从功能上讲,这就是延迟加载的概念。我想我在这里问的只是技术实现。@Paco,进一步。。。不,我不想让我的连接保持打开状态,因为我相信我的连接只在发生故障的情况下保持打开状态是昂贵的,会话应该处理好它。我不同意你关于session==UoW的观点,一个session不一定是短时间运行的UoW,你也可以有一个长时间运行的session,只要你想执行一个动作,你就可以连接和断开它。例如,请参见NH中的示例,它们将会话保留在ASP.NET会话中。由于一级缓存需要大量内存,因此将会话保留在ASP.NET会话中可能会导致内存问题。连接已经由会话管理,因此无需手动打开/关闭连接。保持会话打开不会耗尽您的连接池。session==UoW不是我发明的,而是NHibernate的创建者发明的。