【问题标题】:lazy-loading fails when session got disconnected会话断开时延迟加载失败
【发布时间】:2010-02-17 20:13:52
【问题描述】:

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

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

NHibernate.LazyInitializationException

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

有没有办法(拦截器)自动检测应用程序正在尝试访问一个未初始化的属性,以便拦截器可以在工作单元后快速打开连接并关闭它?

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

【问题讨论】:

    标签: nhibernate


    【解决方案1】:

    没有有效的方法来做到这一点。这个想法是您保持会话打开,直到您完成会话。每个工作单元应该有一个会话。 (会话实际上是一种工作单元)。

    在一个查询中获取您需要的所有内容比在多个查询中获取您需要的所有内容更有效,因此我不同意您最后的说法。延迟加载对懒惰的程序员(比如我)很有用,但从来没有比急切加载更有效。延迟加载可以为您节省一些编程时间,但您仍然需要注意正在执行的许多查询(选择 N+1)

    【讨论】:

    • 关于您的查询计数问题...您可以通过在持久性单元中使用批量加载来减轻这种影响(因此,当您访问 Parent 实例的“子”时,NHibernate 最多``BatchSize "child"ren for all "current known" Parents. 我让您查看文档以了解更多信息。此外,当“大多数时间”您不这样做时,延迟加载平均比 Eager 更有效使用 Parent 实体的“懒惰的孩子”。它最终高度依赖于用例。
    • @Romain Muller:1.) 批处理可用于多种性能优化,其中选择 n+1 是其中之一。另一个是分页,我用它来做更多事情,但是批处理并不能阻止每次选择 n+1,它只会将“选择 n+1”转换为“选择 n/b + 1”。 2.) 不加载与惰性加载和急切加载不同。我的意思不是在映射中使用 eager,我的意思是在查询中使用 eager。
    • @Paco,我并没有真正参与是否要延迟加载的讨论......我已经决定这样做了。我的数据访问层给了我一个对象,在 10 次中有 7 次我只是按原样使用它。 10 次中有 3 次需要后取一些惰性属性。我确实接受了性能瓶颈,并且我知道 N+1。这是我意义上的延迟加载的想法(功能上)。我想我在这里问的只是技术实现。
    • @Paco,Futher... 不,我不想让我的连接保持打开状态,因为我相信我的连接只有在“以防万一”的情况下才能保持打开状态,并且会话应该小心其中。关于“会话 == UoW”,我不同意您的看法,会话不必是短期运行的 UoW,您也可以进行长时间运行的会话,您可以随时连接和断开连接行动。例如,请参阅 NH 中的示例,它们将会话保留在 ASP.NET 会话中。
    • 在 asp.net 会话中保持会话可能会给您带来内存问题,因为一级缓存需要大量内存。连接已经由会话管理,因此无需手动打开/关闭连接。保持会话打开不会耗尽您的连接池。 “session == UoW”不是我发明的,而是 NHibernate 的创造者发明的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 1970-01-01
    • 2011-04-18
    相关资源
    最近更新 更多