NHibernate LazyInitializationException。。如何预防?

NHibernate LazyInitializationException。。如何预防?,nhibernate,Nhibernate,我在生产web服务器上遇到以下错误: NHibernate.LazyInitializationException : Initializing[Domain.Entities.AudienceTypes.Region#4]-failed to lazily initialize a collection of role: Domain.Entities.AudienceTypes.Region.PeerGroups, no session or session was closed 这

我在生产web服务器上遇到以下错误:

NHibernate.LazyInitializationException
: 
Initializing[Domain.Entities.AudienceTypes.Region#4]-failed to lazily initialize a 
collection of role: Domain.Entities.AudienceTypes.Region.PeerGroups, 
no session or session was closed

这不好。让应用程序重新工作的唯一方法是重置IIS,这实际上不是一个选项。这是什么意思?如何防止这种情况发生?

默认情况下,关系是惰性的。这意味着只有当您访问保存关系的属性时,才会执行用于加载关系的SQL查询

问题是,如果在会话关闭的情况下访问一个以前从未调用过的lazy属性,则会出现该错误。 您必须提供以下解决方案:

  • 在完成之前不要关闭会话
  • 在关闭会话之前,请访问稍后将使用的所有惰性属性

在处理完对象之前,不要关闭会话

这是与NHIbernate IMHO合作的最大挑战之一:定义会话边界

在ASP.NET应用程序中,这非常简单:会话在请求开始时启动,您可以在请求结束时关闭会话

在WinForms应用程序中,这有点困难:您必须清楚地定义会话何时启动以及会话何时关闭的边界。 在WinForms应用程序中,我通常定义代表某种工作单元的“任务”。每个任务都有一个会话。创建任务时创建/打开会话,任务完成时关闭会话


接下来,您还可以将一些关联定义为非惰性。但是,您应该确保这样做不会影响性能。

根据Frederik和lujop的回答,如果您正在使用ASP.NET应用程序(正如您提到的web服务器所建议的那样),最好使用依赖项注入框架(如Castle Windor)来处理iSession的生命周期。温莎城堡有一个“PerWebRequest”的生活方式设置,它可以为您实现这一点

否则,在每个请求的开头手动创建一个ISession,该ISession在请求结束时被销毁(可能自动刷新)。然后您的应用程序可以使用此会话


这肯定与ISession在您认为是关闭之前就关闭有关。

要避免此问题,您需要更改Region mapping类中对等组的引用,如下所示

References(x => x.PeerGroupId, "PeerGroupId").Fetch.Join(); 引用(x=>x.PeerGroupId,“PeerGroupId”).Fetch.Join();
添加Fetch.Join()将防止LazyInitializationException。

这是实际的答案。