我有一个多线程的Windows服务应用程序。我在该应用程序的数据访问层中使用了NHibernate。
对于此应用程序中的会话管理,您有什么建议?我读到了关于UNHAddins的内容,这是一个好的解决方案吗?
我有一个多线程的Windows服务应用程序。我在该应用程序的数据访问层中使用了NHibernate。
对于此应用程序中的会话管理,您有什么建议?我读到了关于UNHAddins的内容,这是一个好的解决方案吗?
我使用NHibernate内置的上下文会话(contextual sessions)。您可以在此处了解更多信息:
http://nhibernate.info/doc/nhibernate-reference/architecture.html#architecture-current-session
以下是我使用它的示例:
public class SessionFactory
{
protected static ISessionFactory sessionFactory;
private static ILog log = LogManager.GetLogger(typeof(SessionFactory));
//Several functions omitted for brevity
public static ISession GetCurrentSession()
{
if(!CurrentSessionContext.HasBind(GetSessionFactory()))
CurrentSessionContext.Bind(GetSessionFactory().OpenSession());
return GetSessionFactory().GetCurrentSession();
}
public static void DisposeCurrentSession()
{
ISession currentSession = CurrentSessionContext.Unbind(GetSessionFactory());
currentSession.Close();
currentSession.Dispose();
}
}
另外,在我的Hibernate配置文件中,我还有以下内容:
<property name="current_session_context_class">thread_static</property>
我从未查看过 unhaddins,但这是我在处理 WCF 事务时使用的内容,应该也适用于多线程一般性问题。
这是会话上下文:
namespace Common.Infrastructure.WCF
{
public class NHibernateWcfSessionContext : ICurrentSessionContext
{
private readonly ISessionFactoryImplementor factory;
public NHibernateWcfSessionContext(ISessionFactoryImplementor factory)
{
this.factory = factory;
}
/// <summary>
/// Retrieve the current session for the session factory.
/// </summary>
/// <returns></returns>
public ISession CurrentSession()
{
Lazy<ISession> initializer;
var currentSessionFactoryMap = OperationContext.Current.InstanceContext.Extensions.Find<NHibernateContextManager>().SessionFactoryMaps;
if (currentSessionFactoryMap == null ||
!currentSessionFactoryMap.TryGetValue(factory, out initializer))
{
return null;
}
return initializer.Value;
}
/// <summary>
/// Bind a new sessionInitializer to the context of the sessionFactory.
/// </summary>
/// <param name="sessionInitializer"></param>
/// <param name="sessionFactory"></param>
public static void Bind(Lazy<ISession> sessionInitializer, ISessionFactory sessionFactory)
{
var map = OperationContext.Current.InstanceContext.Extensions.Find<NHibernateContextManager>().SessionFactoryMaps;;
map[sessionFactory] = sessionInitializer;
}
/// <summary>
/// Unbind the current session of the session factory.
/// </summary>
/// <param name="sessionFactory"></param>
/// <returns></returns>
public static ISession UnBind(ISessionFactory sessionFactory)
{
var map = OperationContext.Current.InstanceContext.Extensions.Find<NHibernateContextManager>().SessionFactoryMaps;
var sessionInitializer = map[sessionFactory];
map[sessionFactory] = null;
if (sessionInitializer == null || !sessionInitializer.IsValueCreated) return null;
return sessionInitializer.Value;
}
}
}
这是上下文管理器:
namespace Common.Infrastructure.WCF
{
class NHibernateContextManager : IExtension<InstanceContext>
{
public IDictionary<ISessionFactory, Lazy<ISession>> SessionFactoryMaps = new Dictionary<ISessionFactory, Lazy<ISession>>();
public void Attach(InstanceContext owner)
{
//We have been attached to the Current operation context from the ServiceInstanceProvider
}
public void Detach(InstanceContext owner)
{
}
}
}
为了明确,正如其他答案所述,线程静态上下文将可以直接使用。我提供的主要优点是1)您可以控制它,2)这是一种惰性实现,因此如果不必要,您无需为每个线程启动会话。在我看来,与数据库的连接越少越好。