1

我正在使用 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();
    }
}

编辑

Diego 几乎做到了,但我对此进行了更多思考,我记得我自己实现该控制的主要原因:事务。

我是洋葱架构师,所以我的域对象(知道何时开始事务的对象)无法访问基础设施,因此他们无法开始事务。

为了解决这个问题,我使用延迟初始化,并且总是在打开 Session 时启动事务。当请求结束并且没有捕获到异常时,就会发生提交。除此之外,Ayende 的建议是始终使用事务,即使在查询时也是如此。有什么想法吗?

4

1 回答 1

3

虽然没有直接回答你的问题,但我想:为什么?

会话是一个轻量级对象。如果你不使用它,它只是初始化一些内部结构,但它不会打开数据库连接或任何东西。

有一些例子(只是谷歌)避免为静态对象打开会话以节省一点时间/内存。除此之外,这可能不值得,除非您的分析表明它正在损害您的表现。

更新:对于交易需求,请查看 uNhAddIns 中的 CpBT 实现。

于 2010-12-17T13:28:35.387 回答