Asp.net mvc 如何在我的项目中实现一个健壮的每请求会话模式,同时关注信息隐藏?

Asp.net mvc 如何在我的项目中实现一个健壮的每请求会话模式,同时关注信息隐藏?,asp.net-mvc,nhibernate,session,information-hiding,Asp.net Mvc,Nhibernate,Session,Information Hiding,我目前正在构建一个ASP.NETMVC项目,其中NHibernate作为其持久层 目前,已经实现了一些功能,但只使用本地NHibernate会话:访问数据库(读或写)的每个方法都需要使用“using()”子句实例化自己的NHibernate会话 问题是我想利用NHibernate的延迟加载功能来提高项目的性能 这意味着在呈现视图之前,每个请求都有一个打开的NHibernate会话。此外,必须支持同时请求(同时支持多个会话) 我怎样才能尽可能干净地做到这一点 我在网上搜索了一下,了解了每请求会话模

我目前正在构建一个ASP.NETMVC项目,其中NHibernate作为其持久层

目前,已经实现了一些功能,但只使用本地NHibernate会话:访问数据库(读或写)的每个方法都需要使用“using()”子句实例化自己的NHibernate会话

问题是我想利用NHibernate的延迟加载功能来提高项目的性能

这意味着在呈现视图之前,每个请求都有一个打开的NHibernate会话。此外,必须支持同时请求(同时支持多个会话)

我怎样才能尽可能干净地做到这一点

我在网上搜索了一下,了解了每请求会话模式。我看到的大多数实现都使用某种Http*(HttpContext等)对象来存储会话。此外,使用Application_BeginRequest/Application_EndRequest函数也很复杂,因为当我只想为每个请求实例化一次会话时,它们会为每个HTTP请求(aspx文件、css文件、js文件等)触发

我担心的是,我不希望我的视图或控制器能够访问NHibernate会话(或者更一般地说,NHibernate名称空间和代码)。这意味着我不想在控制器级别或视图级别处理会话

我有几个选择。哪一个看起来最好

  • 使用在控制器操作前后触发的拦截器(如GRAILS中的拦截器)。这些将打开和关闭会话/事务。这在ASP.NET MVC世界中可能吗
  • 在Web上下文中使用NHibernate提供的CurrentSessionContext单例。作为一个例子,我认为这是非常有希望的,但这仍然需要控制器级别的过滤器

  • 使用HttpContext.Current.Items存储请求会话。这加上Global.asax.cs中的几行代码,可以很容易地为我提供请求级别的会话。然而,这意味着依赖关系将在NHibernate和我的视图(HttpContext)之间注入

多谢各位

看一看。对于ASP.NET MVC和NHibernate来说,这是一个非常好的体系结构。

您可以添加一个操作过滤器,用于管理您的NHibernate会话和事务。(这可以在操作或控制器级别完成。)下面是一个示例:


将DI与IoC一起使用。大多数IoC都有每个请求的实例化行为。

伙计们,经过几天的工作,我终于决定使用HttpContext.Current.Items来加载会话

它工作得很好

我是这样做的

import System.Web
class SessionManager {
    public static ISession GetSession()
        var session = HttpContext.Current.Items["NHibernateSession"];
        if (session == null) {
            session = ...; // Create session, like SessionFactory.createSession()...
            HttpContext.Current.Items.Add("NHibernateSession", session);
        }
        return session;
    }

    public static void CloseSession()
    {
        var session = HttpContext.Current.Items["NHibernateSession"];
        if (session != null) {
            if (session.IsOpen) {
                session.close();
            }
            HttpContext.Current.Items.Remove("NHibernateSession");
        }
    }
}
通过使用此类提供的静态方法,可以获得与当前HttpContext(当前Web请求)绑定的会话(例如,在控制器中)。当请求完成时,我们需要另一段代码来调用CloseSession()方法

在Global.asax.cs中:

protected void Application_EndRequest(object sender, EventArgs args)
{
    NHibernateSessionManager.CloseSession();
}
当会话完成时,会自动调用Application_EndRequest事件,因此可以正确地关闭和处置会话。这是有用的,因为否则我们将不得不在每个控制器中执行此操作

我的“解决方案”包括使用Unity在控制器中为每个请求注入会话:


“将在NHibernate和我的视图之间注入依赖关系”->您不太清楚这是什么意思,您能进一步解释吗?如果我使用HttpContext存储NHibernate会话,我的MVC应用程序的视图方面将与数据访问方面(NHibernate会话)相结合@ggervais:只有在视图中使用惰性加载时才会发生这种情况,而你不应该这样做。@mauricio scheffer:那么,我应该怎么做呢?例如,如果我需要在HTML中显示大量提交,我将直接在视图中执行类似User.submissions.Count()的操作。但是,控制器或模型层中的NHibernate可能尚未加载Submissions集合。此外,控制器和视图都是基于每个请求实例化的。NHibernate会话不应该以同样的方式进行吗?最后,如果我听从您的建议,如何确保我的objet在视图中已完全加载(仅所需的属性),同时仍然使用延迟加载?我认为存在一些误解。。。如果您希望视图完全不受NHibernate限制,唯一的方法是在将数据传递给视图之前,急切地在控制器/服务中获取视图所需的所有内容。在控制器/服务中,您可以随意使用延迟加载。这与每个请求的NHibernate会话无关(它应该是这样的,而且几乎每个人都使用HttpModule执行此操作),您能为我们这些试图了解如何设置此会话的人提供更多详细信息吗?我认为这可能会在您进行单元测试时产生问题,需要注意同样的问题。我发现了这个链接,这可能是一个很好的选择。有什么好的建议吗?