MissingTransactionException при запуске NHibernate с Castle.Facilities.AutoTx
Я пытаюсь настроить Castle Windsor с помощью NHibernate и Castle.Facilities.AutoTx, но у меня продолжают возникать проблемы с PerTransactionLifeStyleOption
, Если я сделаю
var sessionFactory = Container.Resolve<Func<ISession>>();
var session = sessionFactory();
Я получаю следующее исключение (во второй строке выше):
Castle.Facilities.AutoTx.MissingTransactionException: нет транзакции в контексте при попытке создать экземпляр модели "NHibernate.ISession" для типа разрешения "NHibernate.ISession". Если вы убедились, что ваш стек вызовов содержит метод с атрибутом [Transaction], то также убедитесь, что вы зарегистрировали средство AutoTx. at Castle.Facilities.AutoTx.Lifestyles.PerTransactionLifestyleManagerBase.Resolve(контекст CreationContext) в каталоге d:\Builds\Castle.Transactions-beta\src\Castle.Facilities.AutoTx\Lifestyles\PerTransactionLifestyleManagerBabilities.ase..Lifestyles.WrapperResolveLifestyleManager`1.Resolve(контекст CreationContext) в d: \ Builds \ Castle.Transactions-beta \ src \ Castle.Facabilities.AutoTx\Lifestyles\WrapperResolveLifestyleManager.cs: строка 143 в замок.Молкер (Контекст CreationContext, Boolean требует Decommission, Boolean instanceRequired) в Castle.MicroKernel.Handlers.AbstractHandler.Resolve(Контекст CreationContext, Boolean instanceRequired) в замке Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CrenelConf.Rec) Обработчик IHandler, Служба типов, дополнительные аргументы IDictionary) в Castle.MicroKernel.DefaultKernel.Resolve (Служба типов, аргументы IDictionary) в Castle.Faciliti es.TypedFactory.TypedFactoryComponent.Resolve (ядро IKernel) в Castle.Facilities.TypedFactory.Resolve.Invoke (вызов IInvocation) в замке. Castle.Proxies.Func`1Proxy.Invoke() в IntegrationTest.NCVIB.WindsorIoC.LocalDbTest.get_Reader() в D:\Projects\NCVIB-GIT\NCVIB\src\IntegrationTest.NCVIB\WindsorIoC\LocalDbTest.cs at 22: IntegrationTest.NCVIB.InspectionObjectMapTests.ReadWrite() в D:\Projects\NCVIB-GIT\NCVIB\src\IntegrationTest.NCVIB\InspectionObjectMapTests.cs: строка 34
Вот компиляция вызовов установки, которые я делаю (на самом деле они распределены по нескольким различным установщикам):
container.AddFacility<AutoTxFacility>();
container.Register(Component.For<INHibernateInstaller>().Instance(new FluentNHibernateInstaller));
container.AddFacility<NHibernateFacility>(fac => fac.Option = DefaultSessionLifeStyleOption.SessionPerTransaction);
FluentNHibernateInstaller
показано здесь:
public class FluentNHibernateInstaller : INHibernateInstaller
{
public FluentConfiguration BuildFluent()
{
return Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2005
.DefaultSchema("dbo")
.ConnectionString(b => b.Is(ConnectionString ?? ConnectionStringChooser.GetConnectionString())))
.Cache(c => c.UseQueryCache().ProviderClass<SysCacheProvider>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserMap>().Conventions.AddFromAssemblyOf<EnumConvention>())
.ExposeConfiguration(
c => c.SetProperty(Environment.SqlExceptionConverter, typeof (MsSqlExceptionConverter).AssemblyQualifiedName))
.ExposeConfiguration(c => c.SetProperty(Environment.ShowSql, "true"));
}
public string ConnectionString { get; set; }
public void Registered(ISessionFactory factory)
{
}
public bool IsDefault
{
get { return true; }
}
public string SessionFactoryKey
{
get { return "default.sf"; }
}
public Maybe<IInterceptor> Interceptor
{
get { return Maybe.None<IInterceptor>(); }
}
}
2 ответа
Оказывается, что AutoTxFacility ДОЛЖЕН быть добавлен в контейнер до любого любого компонента, который имеет атрибут [Transaction].
Я добавлял средство в один из нескольких классов IWindsorInstaller, в котором порядок установки был "случайным", что приводило к установке средства ПОСЛЕ некоторых моих компонентов с транзакционными методами:
var container = new WindsorContainer();
container.Install(FromAssembly.This);
Но теперь я добавляю средство ДО установки из моих классов установки:
var container = new WindsorContainer();
container.AddFacility<AutoTxFacility>();
container.Install(FromAssembly.This());
Вот как будет выглядеть использование:
public class MyClass
{
private readonly Func<ISession> _sessionFactory;
public MyClass(Func<ISession> sessionFactory)
{
_sessionFactory = sessionFactory;
}
[Transaction]
public virtual void UseTheSessionForSomething()
{
// The transaction (and session) will be initialized
// because of the
// [Transaction] attribute
// AND this method is virtual
// AND this instance was resolved from the container
MethodWithinTransactionScope();
}
public void MethodWithinTransactionScope()
{
// Method just needs to be invoked in the scope of a transaction
var session = _sessionFactory();
session.Get<Entity>(1);
}
}
public void Test()
{
var myInstance = container.Resolve<MyClass>();
myInstanace.UseTheSessionForSomething();
}
Это исключение говорит; ответ заключается в добавлении транзакции вокруг метода со строкой кода: var session = sessionFactory();
Если вы получаете исключение и добавили [Transaction] к этому методу, значит, вы не разрешаете службу LocalDbTest должным образом.
Взгляните на мой быстрый старт для быстрого старта: https://github.com/haf/Castle.Facilities.NHibernate/wiki/NHibernate-Facility---Quick-Start
Я сейчас читаю ваш код;), причина, по которой он отсутствовал, была из-за этой строки:
Это известное "TODO", что вы должны зарегистрировать свое предприятие до того, как ваши компоненты, и я думаю, что это также указано в кратком обзоре.
ура