简体   繁体   English

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

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

I'm currently building an ASP.NET MVC project, with NHibernate as its persistance layer. 我目前正在构建一个ASP.NET MVC项目,NHibernate作为其持久层。

For now, some functionality have been implemented, but only use local NHibernate sessions: each method that accessed the database (read or write) needs to instantiate its own NHibernate session, with the "using()" clause. 目前,已经实现了一些功能,但仅使用本地NHibernate会话:访问数据库(读取或写入)的每个方法都需要使用“using()”子句实例化其自己的NHibernate会话。

The problem is that I want to leverage NHibernate's lazy-loading capabilities to improve the performance of my project. 问题是我想利用NHibernate的延迟加载功能来提高项目的性能。

This implies an open NHibernate session per request until the view is rendered. 这意味着每个请求都会打开一个NHibernate会话,直到呈现视图为止。 Furthermore, simultaneous requests must be supported (multiple Sessions at the same time). 此外,必须支持同时请求(同时多个会话)。

How can I achieve that as cleanly as possible? 我怎样才能尽可能干净地实现这一目标?

I searched the web a little bit and learned about the session-per-request pattern. 我在网上搜索了一下,了解了每个请求的会话模式。 Most of the implementations I saw used some sort of Http* (HttpContext, etc.) object to store the session. 我看到的大多数实现使用某种Http *(HttpContext等)对象来存储会话。 Also, using the Application_BeginRequest/Application_EndRequest functions is complicated, since they get fired for each HTTP request (aspx files, css files, js files, etc.), when I only want to instantiate a session once per request. 此外,使用Application_BeginRequest / Application_EndRequest函数很复杂,因为当我只想为每个请求实例化一次会话时,它们会针对每个HTTP请求(aspx文件,css文件,js文件等)被触发。

The concern that I have is that I don't want my views or controllers to have access to NHibernate sessions (or, more generally, NHibernate namespaces and code). 我担心的是我不希望我的视图或控制器能够访问NHibernate会话(或者更常见的是NHibernate命名空间和代码)。 That means that I do not want to handle sessions at the controller level nor the view one. 这意味着我不想在控制器级别处理会话,也不想在视图级别处理会话。

I have a few options in mind. 我有几个选择。 Which one seems the best? 哪一个看起来最好?

  • Use interceptors (like in GRAILS) that get triggered before and after the controller action. 使用在控制器操作之前和之后触发的拦截器(如GRAILS)。 These would open and close sessions/transactions. 这些将打开和关闭会话/交易。 Is this possible in the ASP.NET MVC world? 这可能在ASP.NET MVC世界中吗?
  • Use the CurrentSessionContext Singleton provided by NHibernate in a Web context. 在Web上下文中使用NHibernate提供的CurrentSessionContext Singleton。 Using this page as an example, I think this is quite promising, but that still requires filters at the controller level. 这个页面为例,我认为这很有希望,但仍需要控制器级别的过滤器。
  • Use the HttpContext.Current.Items to store the request session. 使用HttpContext.Current.Items存储请求会话。 This, coupled with a few lines of code in Global.asax.cs, can easily provide me with a session on the request level. 这与Global.asax.cs中的几行代码相结合,可以轻松地为我提供请求级别的会话。 However, it means that dependencies will be injected between NHibernate and my views (HttpContext). 但是,这意味着将在NHibernate和我的视图(HttpContext)之间注入依赖项。

Thank you very much! 非常感谢你!

Well guys, after a few days' work, I finally decided to use the HttpContext.Current.Items to load the session. 好吧,经过几天的工作,我终于决定使用HttpContext.Current.Items来加载会话。

It works great! 它很棒!

Here's how I did it 这就是我做到的

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");
        }
    }
}

By using the static methods provided by this class, one can get a session (for example, in a Controller) that is tied to the current HttpContext (the current Web request). 通过使用此类提供的静态方法,可以获得与当前HttpContext(当前Web请求)绑定的会话(例如,在Controller中)。 We need another snippet of code to call the CloseSession() method when the request is completed. 我们需要另一段代码来在请求完成时调用CloseSession()方法。

In Global.asax.cs: 在Global.asax.cs中:

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

The Application_EndRequest event is automatically called when the session is completed, so the session can be properly closed an disposed of. 会话完成后会自动调用Application_EndRequest事件,因此可以正确关闭会话并将其处理掉。 This is useful, because otherwise we would have to do this in every Controller! 这很有用,因为否则我们必须在每个Controller中执行此操作!

Use DI along with an IoC. 使用DI和IoC。 Most IoC's come with a per-request instantiation behaviour. 大多数IoC都带有每请求实例化行为。

My "solution" involves using Unity to inject session per request in controllers: 我的“解决方案”涉及使用Unity在控制器中为每个请求注入会话:

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

Take a look at S#arp Architecture . 看看S#arp架构 It is a very nice architecture for ASP.NET MVC and NHibernate. 对于ASP.NET MVC和NHibernate来说,它是一个非常好的架构。

You can add an action filter that can manage your NHibernate session & transactions. 您可以添加一个可以管理NHibernate会话和事务的操作过滤器。 (This can be done at the action or controller level.) Here is an example of it: (这可以在动作或控制器级别完成。)以下是一个示例:

http://weblogs.asp.net/srkirkland/archive/2009/09/03/asp-net-mvc-transaction-attribute-using-nhibernate.aspx 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.

相关问题 如何使用Nhibernate在ASP.NET MVC中实现按请求的会话模式 - How to implement session-per-request pattern in asp.net mvc with Nhibernate NHibernate:如何使用每个请求的会话模式处理基于实体的验证,而控制器不知道ISession - NHibernate: how to handle entity-based validation using session-per-request pattern, without controllers knowing about ISession 每个请求会话MVC应用程序的NHibernate问题 - NHibernate problems with a session-per-request MVC appli 如何在不依赖NHibernate的情况下为每个请求实现NHibernate会话? - How can I implement NHibernate session per request without a dependency on NHibernate? “每个请求的会话”模式如何工作? - How does it work the Session Per Request pattern? 如何使用WebAPI / NHibernate实现每次会话会话模式 - How to implement Session Per Conversation pattern with WebAPI/ NHibernate 尝试实现每个Web请求的会话,没有当前的会话上下文配置 - trying to implement session per web request, No current session context configure 每个请求模式和IHttpModule的ASP.NET MVC会话 - ASP.NET MVC session per request pattern and IHttpModule 隐藏来自网址的请求信息 - Hiding request information from url 在MVC控制器中如何获取项目信息? - How do I get project information while in an mvc controller?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM