我正在使用ASP.NET MVC 2编写一个Web应用程序,并选择NHibernate作为我的ORM。我基本上从观看NHibernate夏季系列节目中学习了我的基础知识,并采用了每个请求策略来管理会话的作者会话(Ep 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();
}
}
}
这就是我如何从会话工厂中获取Controller类中我的一个存储库的会话:
CompanyRepository _companyRepository = new CompanyRepository(NHibernateSessionManager.SessionFactory.GetCurrentSession());
答案 0 :(得分:1)
我好奇所以我用Google搜索。
HttpContext.Items可以被多个线程使用。
Nhibernate会话不是线程安全的。
然后有答案:(可能的欺骗) NHibernate thread safety with session
因此,似乎可以有效地管理这种灾难方案。因为你没有发布夏季Nhibernate使用的代码很难说你的实现是否会失败。
答案 1 :(得分:1)
从jfar那里得到一页我觉得我终于教会自己钓鱼(或者可能在正确的方向上投掷我的杆子),并找到了一些很好的文章,阐述了夏季NHibernate计划的工作原理。谷歌搜索NHibernate和Contextual Sessions的更多细节帮助我更好地掌握了这个主题。我还是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来管理你的ISessions: http://ayende.com/Blog/archive/2009/08/05/do-you-need-a-framework.aspx
如果我偏离基础或者不理解某些东西,请随意插入,但据我所知,只要将不同的ISession绑定到每个线程上下文,它将是线程安全的(除非有需要有一个交叉线程的ISession)。