ASP.NET MVC中的NHibernate会话管理

28

我目前正在玩弄Jeffrey Palermo博客文章中发现的HybridSessionBuilder类:

http://jeffreypalermo.com/blog/use-this-nhibernate-wrapper-to-keep-your-repository-classes-simple/

使用此类,我的存储库看起来像这样:

public class UserRepository : IUserRepository
{
    private readonly ISessionBuilder _sessionBuilder;

    public UserRepository(ISessionBuilder sessionBuilder)
    {
        _sessionBuilder = sessionBuilder;
    }

    public User GetByID(string userID)
    {
        using (ISession session = _sessionBuilder.GetSession())
        {
            return session.Get<User>(userID);
        }
    }
}

这是否是管理NHibernate会话/工厂的最佳方法?我听说过工作单元和创建每个Web请求的会话并在结束时刷新它的事情。据我所知,我的当前实现没有做任何这些。基本上,它依靠存储库从会话工厂获取会话并使用它来运行查询。

以这种方式访问数据库有什么缺陷吗?


5个回答

36
您不应该在using语句中包装ISession - 将ISessionBuilder传递到存储库构造函数(依赖注入)的重点是调用代码负责控制ISession的生命周期。如果将其包装在using中,ISession上的Dispose()将被调用,您将无法惰性加载对象成员或将其持久化。
我们通过仅将ISession传递到存储库构造函数中来执行类似操作。据我理解,Palermo先生的代码只是添加了ISession的惰性初始化。我认为这是不必要的,因为如果您不打算使用它,则为什么会新建一个存储库?

10

使用ASP.Net MVC,您需要确保在控制器的Action方法期间维护会话的生命周期,因为一旦您的控制器退出,所有数据都应该被收集。我不确定这种机制是否有助于此。

您可能需要研究S#arp Architechure,它是一个使用nHibernate构建ASP.Net MVC应用程序的库和指南。http://code.google.com/p/sharp-architecture/


我们目前使用 global.asax 中的 begin request 和 end request 调用来管理此会话的生命周期(忽略 css 和 js 等)。不想在每个操作中都添加 Unit Of Work 指令。 - Perhentian
1
我一开始使用的是End Request,但当发生关键错误时,请求已经结束,页面已经呈现,我没有看到一个清晰的处理错误的方法,除了将用户发送到通用页面。我更喜欢在从控制器移动到视图时显式关闭会话(或至少提交事务)。 - JoshBerke

3

它为什么会为静态文件请求打开会话? - Arnis Lapsa
大多数解决方案都使用请求处理程序,因为IIS 7在集成管道中处理所有内容,包括对静态资源的请求,而不仅仅是页面请求。因此,处理程序会为每个请求(包括对静态资源的请求)启动一个Nhibernate事务/会话。 - Ted

1

1

我不会在每个数据请求到NHibernate时打开和关闭会话。我会使用许多其他人建议的工作单元库或进行更多阅读。NHForge.org正在启动,我相信有一些关于为一般Web应用程序设置NHibernate的实践。

NHibernate带给我的“哦哇那很酷”的时刻之一是在开发过程中利用惰性加载集合。能够不必执行所有连接以显示某个关联对象上的数据是一种很棒的体验。

像这样关闭会话,上述情况将不可能发生。

事务方面可能也有一些问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接