Использование NHibernateSession от SharpArchitecture в сочетании с другим потоком - PullRequest
3 голосов
/ 30 июня 2011

Я использую SharpArchitecture в приложении ASP.NET MVC 3.Все прекрасно работает.

Использование NHibernateInitializer от SharpArchitecture для инициализации нового сеанса для каждого запроса, например, так:

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

Как видите, мы также обращаемся к нескольким базам данных.Все в порядке.

Здесь я столкнулся с проблемой.

Мне нужно ускорить отдельный поток для выполнения механизма опроса базы данных.Я намеревался сделать что-то вроде этого:

    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.

Вот мой вопрос.Как я могу использовать NHibernateSession от SharpArchitecture и каким-то образом получить его или его копию в моей теме опроса?Я надеюсь, что это можно сделать без необходимости обхода встроенных SessionManager и SessionFactories, используемых SharpArchitecture.

1 Ответ

7 голосов
/ 06 июля 2011

Я предполагаю, что sessionStorage - это SharpArch.Web.NHibernate.WebSessionStorage объект, верно? Если это так, то проблема не столько в том, что сессия NHibernate имеет значение null, возможно, в вашем потоке HttpContext.Current имеет значение null, а объект WebSessionStorage использует HttpContext.Current для своей работы (см. этот код , особенно строка 37, где при вызове из потока контекст имеет значение null, поэтому возникает исключение null).

Я думаю, что решением было бы написать другой объект SessionStorage, который проверяет, имеет ли HttpContext.Current значение NULL, и если это так, используйте вместо этого локальное хранилище потоков для хранения сеансов NHibernate (это решение взято из этой другой статьи StackOverflow). которая говорит о том же: NullReferenceException при инициализации NServiceBus в веб-приложении. Метод Application_Start )

EDIT

Что-то вроде этого возможно:

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 не будет запущен после завершения потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...