对于Web应用程序,处理会话似乎是一种好方法,即使用设置<property name="current_session_context_class">managed_web</property>
,在Begin / EndRequest上调用CurrentSessionContext.Bind/Unbind
。然后我可以在存储库类中使用sessionFactory.GetCurrentSession()
。
这适用于所有页面请求。但我有后台工作人员在做东西并使用相同的存储库类来做事情。这些不在Web请求中运行,因此会话处理将不起作用。
有关如何解决此问题的任何建议?
答案 0 :(得分:15)
我通过创建自己的会话上下文类来解决它:
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;
}
}
}
答案 1 :(得分:2)
我发现在这种情况下最简单的方法是使用DI库和“混合”范围自己处理会话创建(在StructureMap中,这被定义为InstanceScope.Hybrid)。这将通过ASP.net应用程序域中的HttpContext和普通应用程序域中的ThreadStatic来实例化范例,允许您在两者中使用相同的方法。
我确信其他DI库提供了类似的功能。
答案 2 :(得分:0)
在我的项目中,我在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();
}
}