繁体   English   中英

如何在我的项目中实现强大的每个请求会话模式,同时专注于信息隐藏?

[英]How can I implement a robust session-per-request pattern in my project, while focusing on information hiding?

我目前正在构建一个ASP.NET MVC项目,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 Singleton。 这个页面为例,我认为这很有希望,但仍需要控制器级别的过滤器。
  • 使用HttpContext.Current.Items存储请求会话。 这与Global.asax.cs中的几行代码相结合,可以轻松地为我提供请求级别的会话。 但是,这意味着将在NHibernate和我的视图(HttpContext)之间注入依赖项。

非常感谢你!

好吧,经过几天的工作,我终于决定使用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请求)绑定的会话(例如,在Controller中)。 我们需要另一段代码来在请求完成时调用CloseSession()方法。

在Global.asax.cs中:

protected void Application_EndRequest(object sender, EventArgs args)
{
    NHibernateSessionManager.CloseSession();
}

会话完成后会自动调用Application_EndRequest事件,因此可以正确关闭会话并将其处理掉。 这很有用,因为否则我们必须在每个Controller中执行此操作!

使用DI和IoC。 大多数IoC都带有每请求实例化行为。

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

http://letsfollowtheyellowbrickroad.blogspot.com/2010/05/nhibernate-sessions-in-aspnet-mvc.html

看看S#arp架构 对于ASP.NET MVC和NHibernate来说,它是一个非常好的架构。

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

http://weblogs.asp.net/srkirkland/archive/2009/09/03/asp-net-mvc-transaction-attribute-using-nhibernate.aspx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM