Jon*_*ian 3 nhibernate multithreading sharp-architecture asp.net-mvc-3
我在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,
new[] { Server.MapPath("~/bin/" + ApplicationSettings.Instance.NHibernateMappingAssembly) },
new AutoPersistenceModelGenerator().Generate(),
Server.MapPath("~/NHibernateForOtherDb.config"), null, null, null);
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我们也在访问多个数据库.一切都很好.
这是我遇到问题的地方.
我需要启动一个单独的线程来执行数据库轮询机制.我的意图是做这样的事情:
protected void Application_Start()
{
....
ThreadingManager.Instance.ExecuteAction(() =>
{
// initialize another NHibernateSession within SharpArchitecture somehow
NHibernateInitializer.Instance().InitializeNHibernateOnce(InitializeNHibernateSession);
var service = container.Resolve<IDatabaseSynchronizationService>();
service.SynchronizeRepositories();
});
}
Run Code Online (Sandbox Code Playgroud)
通过我的SynchronizationService,一些存储库被调用.显然,当他们尝试访问其会话时,会抛出异常,因为Session为null.
这是我的问题.我如何利用SharpArchitecture的NHibernateSession并以某种方式获得它或它的副本,在我的轮询线程中旋转?我希望这可以在不必绕过使用SharpArchitecture使用的内置SessionManagers和SessionFactories的情况下完成.
我认为这sessionStorage是一个SharpArch.Web.NHibernate.WebSessionStorage对象,对吗?如果是这样那么问题不在于NHibernate会话是空的,它可能在你的线程上,HttpContext.Current为null,而WebSessionStorage对象依赖于HttpContext.Current来完成它的工作(参见这段代码,特别是行37,其中,当从线程调用时,context为null,因此发生null异常).
我认为解决方案是编写一个不同的SessionStorage对象来检查是否HttpContext.Current为null,如果是,则使用线程本地存储来代替存储NHibernate会话(这个解决方案是从其他StackOverflow文章中找到的,该文章讨论了相同的类型事物:在Web应用程序Application_Start方法中初始化NServiceBus时出现NullReferenceException)
编辑
也许这样的东西:
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 );
}
}
Run Code Online (Sandbox Code Playgroud)
注意:您必须确保NHibernateSession.CloseAllSessions()在完成线程完成工作后调用,因为当线程完成时,Application_EndRequest不会被触发.
| 归档时间: |
|
| 查看次数: |
2186 次 |
| 最近记录: |