使用 WebSessionContext/CurrentSessionContext 延迟初始化 ISession
我正在使用 NHibernate 3 启动一个新项目,并尝试将 CurrentSessionContext API 与 WebSessionContext 结合使用来管理我的 ISession 对象。
在以前的项目中,我总是自己管理,因此每当我需要 ISession 对象时,我都会创建它并将其存储在 HttpContext.Items 集合中。非常简单,但使用本机解决方案(CurrentSessionContext)似乎是这个新项目的最佳选择。
当我管理该对象时,我能够对其进行延迟初始化,这意味着我只会在需要时打开会话,而不是在每个请求中打开会话,因为我可能不需要它,并且打开所有会话会浪费资源/时间时间。
有没有一种简单的方法可以使用 CurrentSessionContext API 来做到这一点?
这是我在 HttpModule 中使用的负责此操作的代码:
public class ContextualSessionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
public void Dispose()
{
}
private static void context_BeginRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
BindSession(context);
}
private static void BindSession(HttpContext context)
{
// Create a new session (it's the beginning of the request)
var session = SessionBuilderFactory.CurrentSessionFactory.OpenSession();
// Tell NH session context to use it
CurrentSessionContext.Bind(session);
}
private static void context_EndRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
UnbindSession(context);
}
private static void UnbindSession(HttpContext context)
{
// Get the default NH session factory
var factory = SessionBuilderFactory.CurrentSessionFactory;
// Give it to NH so it can pull the right session
var session = CurrentSessionContext.Unbind(factory);
if (session == null) return;
session.Flush();
session.Close();
}
}
编辑
迭戈几乎做到了这一点,但我对此想得更多一些,我记得我自己实现该控件的主要原因: 交易。
我是一个 洋葱架构 人,所以我的域对象(他们是那些知道何时开始交易的人)无法访问基础设施,因此他们无法开始交易。
为了解决这个问题,我使用延迟初始化并始终在打开会话时启动事务。当请求结束并且没有捕获到异常时发生提交。 除此之外,Ayende 建议始终使用事务,即使在查询时也是如此。有什么想法吗?
I'm starting a new project with NHibernate 3 and I'm trying to use the CurrentSessionContext API with WebSessionContext to manage my ISession object.
In previous projects I always managed that myself so whenever I needed a ISession object I would create it and store in HttpContext.Items collection. Pretty straightforward, but using a native solution (CurrentSessionContext) seems like a best option for this new project.
When I managed the object I was able to do a lazy initialization on it, meaning that I would only open a Session when I needed it and not in every request because I may not need it and would be wasting resource/time by opening it all the time.
Is there a simple way to do that with the CurrentSessionContext API?
Here is the code I'm using in the HttpModule responsible for this:
public class ContextualSessionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
public void Dispose()
{
}
private static void context_BeginRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
BindSession(context);
}
private static void BindSession(HttpContext context)
{
// Create a new session (it's the beginning of the request)
var session = SessionBuilderFactory.CurrentSessionFactory.OpenSession();
// Tell NH session context to use it
CurrentSessionContext.Bind(session);
}
private static void context_EndRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
UnbindSession(context);
}
private static void UnbindSession(HttpContext context)
{
// Get the default NH session factory
var factory = SessionBuilderFactory.CurrentSessionFactory;
// Give it to NH so it can pull the right session
var session = CurrentSessionContext.Unbind(factory);
if (session == null) return;
session.Flush();
session.Close();
}
}
Edit
Diego pretty much nailed it, but I thought a little bit more about this and I remembered the main reason why I implemented that control myself: transactions.
I'm a Onion Architecture guy so my domain objects (who are the ones who know when to start a transaction) does not have access to infrastructure so they cannot start transactions.
In order to solve this, I use lazy initialization and always start a transaction when opening a Session. Committing happens when the request ends and no exceptions were caught.
Besides this, there is Ayende's advice to always use transactions, even when querying. Any thoughts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
虽然没有直接回答您的问题,但我认为:为什么?
会话是一个轻量级对象。如果你不使用它,它只是初始化一些内部结构,但它不会打开数据库连接或任何东西。
有一些例子(只是谷歌)可以避免为静态对象打开会话,以节省一点时间/内存。除此之外,它可能不值得,除非您的分析表明它会损害您的性能。
更新:对于事务需求,请查看 uNhAddIns 中的 CpBT 实现。
While not directly answering your question, I think: why?
A session is a lightweight object. If you don't use it, it just initializes some internal structures, but it doesn't open a DB connection or anything.
There are some examples around (just Google) to avoid opening sessions for static objects in order to save a little time/memory. Other than that, it might not be worth it, unless your profiling shows it's hurting your performance.
Update: for transaction needs, have a look at the CpBT implementation in uNhAddIns.