现在,已经实现了一些功能,但是仅使用本地NHibernate会话:访问数据库(读或写)的每个方法都需要使用“using()”子句实例化自己的NHibernate会话.
问题是我想利用NHibernate的延迟加载功能来改善我的项目的性能.
这意味着每个请求直到视图呈现为一个开放的NHibernate会话.此外,必须支持同时发送的请求(同时进行多个会话).
我该如何尽可能干净地实现?
我在网上搜了一下,并了解了每个请求模式的模式.我看到的大多数实现使用了一些Http *(HttpContext等)对象来存储会话.此外,使用Application_BeginRequest / Application_EndRequest函数是复杂的,因为它们每个请求都会针对每个HTTP请求(aspx文件,css文件,js文件等)触发,当我只想要每个请求实例化一次会话.
我所关心的是,我不希望我的意见或控制器能够访问NHibernate会话(或更一般地,NHibernate命名空间和代码).这意味着我不想处理控制器级别的会话或视图.
我有几个选择.哪一个似乎最好?
>使用控制器操作之前和之后触发的拦截器(如GRAILS中).这些将打开和关闭会话/交易.这是可能在ASP.NET MVC世界吗?
>使用NHibernate在Web上下文中提供的CurrentSessionContext Singleton.以this page为例,我认为这是非常有希望的,但是在控制器层面仍然需要过滤器.
>使用HttpContext.Current.Items存储请求会话.这加上Global.asax.cs中的几行代码,可以轻松地在请求级别提供一个会话.但是,这意味着NHibernate和我的视图(HttpContext)之间将依赖关系.
非常感谢你!
解决方法
它的作品很棒!
这是我如何做到的
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事件,因此可以正确关闭会话.这是有用的,因为否则我们必须在每个控制器中这样做!