NServiceBus 3.2 и дочерние контейнеры

У меня есть настройка NServiceBus (3.2.2) с Castle Windsor в качестве его построителя, и я также использую NHibernate. Моя проблема заключается в том, что в моих обработчиках, если у меня есть несколько репозиториев, которым нужен сеанс NHibernate, они заканчиваются разными сеансами!

В документе NServiceBus указано, что любые экземпляры transient внутри контейнера будут рассматриваться как экземпляры singleton. Также мой сеанс NHibernate обернут абстракцией единицы работы.

Вот код, используемый для настройки NServiceBus с NHibernate:

IWindsorContainer container = new WindsorContainer(new XmlInterpreter());
container.Install(new ContainerInstaller());
container.Install(new UnitOfWorkInstaller(AppDomain.CurrentDomain.BaseDirectory, LifestyleType.Transient));
container.Install(new FactoryInstaller(AppDomain.CurrentDomain.BaseDirectory, LifestyleType.Transient));
container.Install(new RepositoryInstaller(AppDomain.CurrentDomain.BaseDirectory, LifestyleType.Transient));

Configure.With()
    .CastleWindsorBuilder(container)
    .FileShareDataBus(Properties.Settings.Default.DataBusFileSharePath)
    .MsmqTransport()
        .IsTransactional(true)
        .PurgeOnStartup(false)
    .UnicastBus()
         .LoadMessageHandlers()
         .ImpersonateSender(false)
     .JsonSerializer();

UnitOfWorkInstaller что-то вроде:

var fromAssemblyDescriptor = AllTypes.FromAssemblyInDirectory(new AssemblyFilter(_installationPath));
container.Register(fromAssemblyDescriptor
    .IncludeNonPublicTypes()
    .Pick()
    .If(t => t.GetInterfaces().Any(i => i == typeof(IUnitOfWork)) && t.Namespace.StartsWith("Magma"))
    .WithService.AllInterfaces()
    .Configure(con => con.LifeStyle.Is(_lifeStyleType).UsingFactoryMethod(k => k.Resolve<IUnitOfWorkFactory>().Create())));

Поэтому, когда требуется сеанс NHibernate, он создается с помощью файла UnitOfWorkFactory. Я попытался установить для свойства current_session_context_class значение thread_static в конфигурации NHibernate, но это не сработало.

Почему у меня другая единица работы в моих обработчиках NServiceBus?


person Francois Joly    schedule 06.06.2012    source источник
comment
Я не верю в это: в документе NServiceBus говорится, что любые временные экземпляры внутри контейнера будут рассматриваться как экземпляры-одиночки.   -  person mynkow    schedule 07.06.2012
comment
@mynkow NServiceBus создает дочерний контейнер для каждого полученного транспортного сообщения, помните, что транспортные сообщения могут содержать несколько «определенных пользователем сообщений». Это означает, что все временные экземпляры, созданные во время обработки этого сообщения, рассматриваются как синглтоны в дочернем контейнере. Это позволяет вам легко обмениваться, например, сеансом NHibernate между репозиториями, не возясь со статическим кэшированием потоков. соответствующую документацию можно найти здесь   -  person Francois Joly    schedule 07.06.2012
comment
кажется, что с тех пор он изменился, потому что, глядя на исходный код, вы можете увидеть новое перечисление жизненного цикла NServiceBus InstancePerUnitOfWork, означающее, что экземпляр будет одноэлементным на протяжении всей единицы работы. На практике это означает обработку одного транспортного сообщения, и это значение сопоставляется с перечислением LifestyleType.Scoped Windsor Castle... так что я попробую это   -  person Francois Joly    schedule 07.06.2012
comment
также, когда вы используете «current_session_context_class», вы должны получить сеанс, например, sessionFactory.GetCurrentSession()   -  person mynkow    schedule 07.06.2012
comment
@mynkow да, я думаю о рефакторинге этой части моего кода, чтобы вместо создания ISession с использованием фабричного метода и предоставления контейнеру возможности управлять временем своего существования я мог бы использовать функцию контекста сеанса NHibernate.   -  person Francois Joly    schedule 07.06.2012


Ответы (1)


У меня все получилось, используя образ жизни Касла LifestyleType.Scoped. Но затем, по уже очевидным причинам, мой обработчик вызывался снова и снова, пока сообщение не попало в очередь ошибок. У меня была эта проблема раньше, и это было связано с откатом или фиксацией транзакции в обработчике. В моем подразделении работы я повторно отменял любые незафиксированные изменения в методе Dispose. Единственное, что мне нужно было сделать, это только удалить сеанс и удалить вызов Rollback.

person Francois Joly    schedule 08.06.2012