8

我有一个存储库类,它定义了一些基本的 Get/Save/Delete 方法。在这些内部,我使用 NHibernate 来处理我的业务实体。例如:

Public Class SecurityRepositoryNHibImpl : Implements ISecurityRepository
    Public Function GetUser(ByVal UUID As System.Guid) As Entities.User Implements ISecurityRepository.GetUser
        Dim eUser As Entities.User
        Using session As ISession = NHibernateHelper.OpenSession()
            eUser = session.Get(Of Entities.User)(UUID)
        End Using
        Return eUser
    End Function
End Class

但是,在我的 User 类中,我有一些属性和其他对象的集合,理想情况下我希望延迟加载。但是,当然,ISession 是在存储库中创建和处置的,我猜这就是为什么,除此之外,当我尝试访问这些属性时,我会收到“无法初始化代理 - 无会话”错误。

那么我唯一的选择是在使用存储库时禁用延迟加载吗?还是有可能(或只是愚蠢)以某种方式将会话纳入业务层的范围?

我确实喜欢存储库模型,并且 NHibernate 正在我身上成长(经过很多最初的挫折试图使其工作),那么你们大师们发现一起使用它们的最佳方式是什么?

一般来说,我对 NHibernate 和存储库模型很陌生(在工作中我们仍然主要使用 VB6!),所以请原谅可能是一个愚蠢的问题。谢谢。


@mookid:谢谢老兄,这真的很有帮助,但我可能会让它打开更长的时间。它是 WCF Web 服务的后端,所有功能都是每次调用的上下文,因此每次调用的会话寿命会很好。只是不确定如何让这样的东西在业务层工作,理想情况下我不希望业务对象必须直接与任何 NHibernate 类交互。我想 NHibernate 会话的某种包装器至少将它抽象出来......嗯,你至少让我走上了正确的轨道。


看起来这里的关键词是“工作单元”,网络上存在大量与 NHibernate 相关的资源。特别是寻找Ayende在 Rhino Commons 中的实现,以及他的 App Architecture 网络广播(Hibernating Rhinos 中的第 9 号),非常有用。起初我很困惑,因为我虽然在业务层中放置“工作单元”会混合关注点,但我很快就得到了纠正。

4

1 回答 1

12

创建您的 ISession 并在您的存储库中显式地处理它对于小型且非常简单的项目来说是可以的 - 但是,正如您所发现的,当您开始想要使用 NHibernate 支持的一些很酷的功能时,它就会变得很短。

您可能应该让会话的生活方式由存储库之外的东西控制 - 例如,如果您正在执行 ASP.NET Web 应用程序,您可能希望将会话保存在当前请求中(HttpContext.Current.Items如果我没记错的话)持续Web 请求,然后在请求结束时提交和处置(如果发生异常则回滚)。

我不知道在 ASP.NET 应用程序中控制会话生活方式的最佳方法,但必须有某种方法可以在每个请求的开头和结尾调用代码。在 ASP.NET MVC 中,它可以通过从覆盖其OnActionExecutingOnActionExecuted方法的基本控制器派生所有控制器来轻松完成。

于 2009-03-16T14:38:01.727 回答