多线程 – 将SharpArchitecture的NHibernateSession与不同的线程
我在ASP.NET MVC 3应用程序中使用SharpArchitecture.一切都很美妙.
使用SharpArchitecture的NHibernateInitializer为每个请求初始化一个新的Session,如下所示: protected void Application_BeginRequest(object sender,EventArgs e) { NHibernateInitializer.Instance().InitializeNHibernateOnce(InitializeNHibernateSession); } private void InitializeNHibernateSession(ISessionStorage sessionStorage) { NHibernateSession.ConfigurationCache = new NHibernateConfigurationFileCache( new[] { "App.Core" }); NHibernateSession.Init( sessionStorage,new[] { Server.MapPath("~/bin/" + ApplicationSettings.Instance.NHibernateMappingAssembly) },new AutoPersistenceModelGenerator().Generate(),Server.MapPath("~/NHibernate.config")); NHibernateSession.AddConfiguration(ApplicationSettings.NHIBERNATE_OTHER_DB,Server.MapPath("~/NHibernateForOtherDb.config"),null,null); } 如您所见,我们也在访问多个数据库.一切都很好. 这是我遇到问题的地方. 我需要启动一个单独的线程来执行数据库轮询机制.我的意图是做这样的事情: protected void Application_Start() { .... ThreadingManager.Instance.ExecuteAction(() => { // initialize another NHibernateSession within SharpArchitecture somehow NHibernateInitializer.Instance().InitializeNHibernateOnce(InitializeNHibernateSession); var service = container.Resolve<IDatabaseSynchronizationService>(); service.SynchronizeRepositories(); }); } 通过我的SynchronizationService,一些存储库被调用.显然,当他们尝试访问其会话时,会抛出异常,因为Session为null. 这是我的问题.我如何利用SharpArchitecture的NHibernateSession并以某种方式获得它或它的副本,在我的轮询线程中旋转?我希望这可以在不必绕过使用SharpArchitecture使用的内置SessionManagers和SessionFactories的情况下完成. 解决方法
我假设sessionStorage是一个SharpArch.Web.NHibernate.WebSessionStorage对象,对吧?如果是这样那么问题不在于NHibernate会话是空的,它可能在你的线程上,HttpContext.Current为null,并且WebSessionStorage对象依赖于HttpContext.Current来完成它的工作(见
this code,特别是第37行),其中,当从线程调用时,context为null,因此发生null异常).
我认为解决方案是编写一个不同的SessionStorage对象,检查HttpContext.Current是否为null,如果是,则使用线程本地存储来存储NHibernate会话(这个解决方案是从其他StackOverflow文章中讨论的同样的事情:NullReferenceException when initializing NServiceBus within web application Application_Start method) 编辑 也许这样的东西: public class HybridWebSessionStorage : ISessionStorage { static ThreadLocal<SimpleSessionStorage> threadLocalSessionStorage; public HybridWebSessionStorage( HttpApplication app ) { app.EndRequest += Application_EndRequest; } public ISession GetSessionForKey( string factoryKey ) { SimpleSessionStorage storage = GetSimpleSessionStorage(); return storage.GetSessionForKey( factoryKey ); } public void SetSessionForKey( string factoryKey,ISession session ) { SimpleSessionStorage storage = GetSimpleSessionStorage(); storage.SetSessionForKey( factoryKey,session ); } public System.Collections.Generic.IEnumerable<ISession> GetAllSessions() { SimpleSessionStorage storage = GetSimpleSessionStorage(); return storage.GetAllSessions(); } private SimpleSessionStorage GetSimpleSessionStorage() { HttpContext context = HttpContext.Current; SimpleSessionStorage storage; if ( context != null ) { storage = context.Items[ HttpContextSessionStorageKey ] as SimpleSessionStorage; if ( storage == null ) { storage = new SimpleSessionStorage(); context.Items[ HttpContextSessionStorageKey ] = storage; } } else { if ( threadLocalSessionStorage == null ) threadLocalSessionStorage = new ThreadLocal<SimpleSessionStorage>( () => new SimpleSessionStorage() ); storage = threadLocalSessionStorage.Value; } return storage; } private static readonly string HttpContextSessionStorageKey = "HttpContextSessionStorageKey"; private void Application_EndRequest( object sender,EventArgs e ) { NHibernateSession.CloseAllSessions(); HttpContext context = HttpContext.Current; context.Items.Remove( HttpContextSessionStorageKey ); } } 注意:您必须确保在完成线程工作后调用NHibernateSession.CloseAllSessions(),因为当线程完成时,Application_EndRequest不会被触发. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |