具有后台工作人员的 Web 应用程序的休眠会话管理策略?
Posted
技术标签:
【中文标题】具有后台工作人员的 Web 应用程序的休眠会话管理策略?【英文标题】:Nhibernate session management strategy for web application with background-workers? 【发布时间】:2011-08-16 18:57:02 【问题描述】:对于 Web 应用程序,处理会话的好方法似乎是使用设置 <property name="current_session_context_class">managed_web</property>
,在 Begin/EndRequest 上调用 CurrentSessionContext.Bind/Unbind
。然后我可以在存储库类中使用sessionFactory.GetCurrentSession()
。
这适用于所有页面请求。但是我有后台工作人员在做事情并使用相同的存储库类来做事情。这些不在网络请求中运行,因此会话处理不起作用。
对如何解决这个问题有什么建议吗?
【问题讨论】:
【参考方案1】:我通过创建自己的会话上下文类解决了这个问题:
public class HybridWebSessionContext : CurrentSessionContext
private const string _itemsKey = "HybridWebSessionContext";
[ThreadStatic] private static ISession _threadSession;
// This constructor should be kept, otherwise NHibernate will fail to create an instance of this class.
public HybridWebSessionContext(ISessionFactoryImplementor factory)
protected override ISession Session
get
var currentContext = ReflectiveHttpContext.HttpContextCurrentGetter();
if (currentContext != null)
var items = ReflectiveHttpContext.HttpContextItemsGetter(currentContext);
var session = items[_itemsKey] as ISession;
if (session != null)
return session;
return _threadSession;
set
var currentContext = ReflectiveHttpContext.HttpContextCurrentGetter();
if (currentContext != null)
var items = ReflectiveHttpContext.HttpContextItemsGetter(currentContext);
items[_itemsKey] = value;
return;
_threadSession = value;
【讨论】:
如果不想引用HttpContext.Current
,可以使用NHibernate.Context.ReflectiveHttpContext
来判断上下文是否可用。这在您不想在数据访问项目中引用 System.Web
的情况下很有用。
非常感谢!对此困惑了半天——我有一个带有 WCF 服务的 WebForms 项目,而CurrentSessionContext.Bind
正在抛出一个NullReferenceException
。你的代码对我来说完美无缺:D
@Allrameest 另外在这个实现中你如何处理 ISession 的翻译?
这就是解决方案!非常感谢:)【参考方案2】:
我发现在这种情况下使用 DI 库和“混合”范围(在 StructureMap 中定义为 InstanceScope.Hybrid)自己处理会话创建最简单。这将通过 ASP.net 应用程序域中的 HttpContext 和普通应用程序域中的 ThreadStatic 来确定实例的范围,从而允许您在两者中使用相同的方法。
我确信其他 DI 库也提供类似的功能。
【讨论】:
这可能会奏效。但我使用的 Castle 没有那种开箱即用的混合生活方式。所以我必须自己建造它。然后构建一个 NHibernate 会话上下文类就更简单了(见我的回答)。但是感谢您间接地给了我这个想法。 :)【参考方案3】:在我的项目中,我围绕 CurrentSessionContext 编写了一个小包装类。
也许您可以扩展它以满足您的需求。
我认为您只需要调整BindSessionToRequest
和GetCurrentSession
的实现即可:
public static class SessionManager
private static ISessionFactory _sessionFactory = null;
private static ISessionFactory SessionFactory
get
if (_sessionFactory == null)
//check whether we're in web context or win context, and create the session factory accordingly.
if (System.Web.HttpContext.Current != null)
if (_sessionFactory == null)
_sessionFactory = DAOBase.GetSessionFactory();
else
_sessionFactory = DAOBase.GetSessionFactoryForWin();
return _sessionFactory;
public static void BindSessionToRequest()
ISession session = SessionManager.SessionFactory.OpenSession();
NHibernate.Context.CurrentSessionContext.Bind(session);
public static bool CurrentSessionExists()
return NHibernate.Context.CurrentSessionContext.HasBind(SessionFactory);
public static void UnbindSession()
ISession session = NHibernate.Context.CurrentSessionContext.Unbind(SessionManager.SessionFactory);
if (session != null && session.IsOpen)
session.Close();
public static ISession GetCurrentSession()
return SessionFactory.GetCurrentSession();
【讨论】:
以上是关于具有后台工作人员的 Web 应用程序的休眠会话管理策略?的主要内容,如果未能解决你的问题,请参考以下文章