在结合使用SharpArchitecture的NHibernateSession用不同的线程 [英] Using SharpArchitecture's NHibernateSession in conjunction with a different thread

查看:187
本文介绍了在结合使用SharpArchitecture的NHibernateSession用不同的线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用在ASP.NET MVC 3应用程序SharpArchitecture。一切奇妙的作品。

I'm using SharpArchitecture in an ASP.NET MVC 3 application. Everything works wonderfully.

使用SharpArchitecture的NHibernateInitializer初始化每个请求一个新的Session,像这样:

Using SharpArchitecture's NHibernateInitializer to initialize a new Session per request like so:

    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);
    }

正如你所看到的,我们也创下多个数据库。所有这很好。

As you can see, we are also hitting multiple databases. All that's fine.

下面就是我遇到的一个问题。

Here's where I run into an issue.

我需要旋转起来一个单独的线程来执行数据库轮询机制。我的目的是做这样的事情:

I need to spin up a separate thread to execute a database polling mechanism. My intention was to do something like this:

    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,一些仓库被调用。显然,当他们试图访问他们的会话,抛出一个异常,因为会议为null。

And through my SynchronizationService, some repositories get called. Obviously when they attempt to access their session, an exception is thrown because the Session is null.

下面是我的问题。我如何利用SharpArchitecture的NHibernateSession并以某种方式把它或它的一个副本,转动我的轮询线程里面呢?我希望可以做到这一点,而无需使用内置的由SharpArchitecture使用SessionManagers和SessionFactories绕过。

Here's my question. How can I leverage SharpArchitecture's NHibernateSession and somehow have it or a copy of it, spun up inside my polling thread? I am hoping this can be done without having to bypass using the built in SessionManagers and SessionFactories used by SharpArchitecture.

推荐答案

我认为的sessionStorage SharpArch.Web.NHibernate.WebSessionStorage 对象,对不对?如果是的话那么问题就没有这么多NHibernate会话为空,这可能是对你的线程,HttpContext.Current为null,并且WebSessionStorage对象依赖于HttpContext.Current做其工作(见<一href=\"http://$c$c.google.com/p/sharp-architecture/source/browse/trunk/src/SharpArch/SharpArch.Web/NHibernate/WebSessionStorage.cs?r=487\">this code ,特别是第37行,在这里,从一个线程调用时,背景为空,所以空异常发生时)。

I assume that sessionStorage is a SharpArch.Web.NHibernate.WebSessionStorage object, right? If so then the issue isn't so much that the NHibernate Session is null, it's probably that on your thread, HttpContext.Current is null, and the WebSessionStorage object relies on HttpContext.Current to do its work (see this code, particularly line 37, where, when called from a thread, context is null, so a null exception occurs).

我认为,解决办法是写检查,看看是否 HttpContext.Current 为空不同的sessionStorage的对象,如果是,使用线程本地存储来存储NHibernate的会议,而不是中(该解决方案从这个StackOverflow的其他文章,其中谈到了同样的事情收集:<一href=\"http://stackoverflow.com/questions/2731462/nullreferenceexception-when-initializing-nservicebus-within-web-application-appli\">NullReferenceException Web应用程序Application_Start方法中内初始化NServiceBus时)

I think the solution would be to write a different SessionStorage object that checks to see if HttpContext.Current is null, and if it is, use thread local storage to store NHibernate Sessions in instead (this solution gleaned from this other StackOverflow article which talks about the same sort of thing: 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会不会被解雇当你的线程完成。

NOTE: You will have to make sure you call NHibernateSession.CloseAllSessions() when you have finished doing your work on the thread though, as Application_EndRequest won't get fired when your thread completes.

这篇关于在结合使用SharpArchitecture的NHibernateSession用不同的线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆