【问题标题】:Web app NHibernate Session Management Summer of NHibernate styleWeb 应用 NHibernate 会话管理 NHibernate 风格的夏天
【发布时间】:2011-04-24 02:09:27
【问题描述】:

我正在使用 ASP.NET MVC 2 编写一个 Web 应用程序,并选择 NHibernate 作为我的 ORM。我基本上是从观看 NHibernate 之夏系列中学到的基础知识,并根据请求策略采用了作者会话来管理会话(第 13 集)。事情似乎运作良好,但我担心这是否是管理会话和线程安全的功能性现实世界方法。如果不是,那么我愿意接受其他示例。

我已添加代码进行详细说明。 这是我设置 SessionFactory 的代码:

public class NHibernateSessionManager
{
    public static readonly ISessionFactory SessionFactory;

    static NHibernateSessionManager()
    {
        try
        {
            Configuration cfg = new Configuration();

            if (SessionFactory != null)
                throw new Exception("trying to init SessionFactory twice!");

            SessionFactory = cfg.Configure().BuildSessionFactory();
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
            throw new Exception("NHibernate initialization failed", ex);
        }
    }
    public static ISession OpenSession()
    {
        return SessionFactory.OpenSession();
    }
}

这是我让网络请求开始和停止事务的地方:

public class NHibernateSessionPerRequestModule : IHttpModule
{
    public void Dispose()
    {
    }

    public void Init(HttpApplication context)
    {
        context.BeginRequest +=new EventHandler(Application_BeginRequest);
        context.EndRequest +=new EventHandler(Application_EndRequest);
    }

    private void Application_BeginRequest(object sender, EventArgs e)
    {
        ISession session = NHibernateSessionManager.OpenSession();
        session.BeginTransaction();
        CurrentSessionContext.Bind(session);
    }
    private void Application_EndRequest(object sender, EventArgs e)
    {
        ISession session = CurrentSessionContext.Unbind(NHibernateSessionManager.SessionFactory);
        if(session != null)
            try
            {
                session.Transaction.Commit();
            }
            catch (Exception)
            {
                session.Transaction.Rollback();
            }
            finally
            {
                session.Close();
            }
    }
}

这就是我如何从会话工厂中为我的控制器类中的一个存储库获取会话:

CompanyRepository _companyRepository = new CompanyRepository(NHibernateSessionManager.SessionFactory.GetCurrentSession());

【问题讨论】:

    标签: asp.net-mvc nhibernate session


    【解决方案1】:

    从 jfar 获取一页,我想我终于自学了在这个主题上钓鱼(或者可能把我的杆子投向了正确的方向),并找到了一些很好的文章,这些文章阐明了 NHibernate 之夏计划是如何运作的。谷歌搜索以查找有关 NHibernate 和上下文会话的更多详细信息有助于我更好地掌握该主题。我对 NHibernate(以及一般的网络编程)还是新手,所以如果这个问题和答案看起来很简单,请多多包涵。

    似乎NHibernate 之夏方案是线程安全的。我的解释将引用我上面的代码示例中的名称。 SessionFactory 变量是静态的,因此它可以从每个线程访问,但是它是一个线程安全的对象(而如上所述 ISession 不是线程安全的)。 NHibernateSessionPerRequestModule 建立了两个事件,它们将在 Web 请求 (Application_BeginRequest) 和一个结束时触发 (Application_EndRequest)。 Application_BeginRequest 将获取一个 ISession 对象,然后您可以将其绑定到当前上下文。这有助于确保 ISession 对象用于 Web 请求期间并且仅用于该线程。在 Web 请求开始后,可以使用 .GetCurrentSession() 检索 ISession,以与 _companyRepository 一起使用。 Application_BeginRequest 也将为您开始交易。 Application_EndRequest 将取消绑定 ISession 对象,在您的 Web 请求结束时提交所有更改,并关闭 ISession。

    Peter Wigle 有一篇文章展示了如何实现会话管理的类似示例: http://pwigle.wordpress.com/2008/11/21/nhibernate-session-handling-in-aspnet-the-easy-way

    在那篇文章中,Global.asax 用于指定绑定和解除绑定的事件,而不是创建 IHttpModule。

    Ayende 有一个很好的干净示例,它使用 HttpContext 来管理您的 ISession: http://ayende.com/Blog/archive/2009/08/05/do-you-need-a-framework.aspx

    如果我偏离了基础或者不理解某些内容,请随意插话,但据我所知,只要将不同的 ISession 绑定到每个线程上下文,它将是线程安全的(除非有需要有一个跨线程的 ISession)。

    【讨论】:

      【解决方案2】:

      我很好奇,所以我四处搜索。

      HttpContext.Items 可以被多个线程使用。

      休眠会话不是线程安全的。

      然后有答案:(可能是骗子) NHibernate thread safety with session

      所以看来这个灾难的秘诀可以有效地管理。因为你没有发布 Summer of Nhibernate 使用的代码,很难说你的实现是否会失败。

      【讨论】:

      • 那么上面的代码,因为ISession是静态的,它不是线程安全的?
      • @mattnss - 阅读我链接的答案。看起来如果您存储会话而不是工厂本身,您可能会遇到麻烦。
      • 所以在我发布的代码中,我只是将 SessionFactory 存储在一个静态变量中,所以它应该是线程安全的?
      • 您应该阅读 static 关键字的作用,教人钓鱼等等。不用说,如果您希望会话对每个控制器和 httprequest 都是唯一的,那么这可能是您能做的最糟糕的事情。
      • 我完全同意教人钓鱼方面。我问这个问题是因为很多人似乎将 NHibernate 的夏季网络广播引用到 NHibernate 新手,很高兴知道以这种方式学习它是否对理论有好处,或者它是否可以作为实践的例子他的会话结束(我知道在他的截屏视频的开头,他确实提到了最初引入的检索会话的方法不是你在现实世界中执行它的方式)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 1970-01-01
      • 2010-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多