我正在尝试使用 NHibernate 和 CaSTLe.Facilities.AutoTx 配置 CaSTLe Windsor,但我不断遇到 PerTransactionLifeStyleOption
问题。如果我这样做
var sessionFactory = Container.Resolve<Func<ISession>>();
var session = sessionFactory();
我收到以下异常(在上面的第二行):
Castle.Facilities.AutoTx.MissingTransactionException: No transaction in context when trying to instantiate model 'NHibernate.ISession' for resolve type 'NHibernate.ISession'. If you have verified that your call stack contains a method with the [Transaction] attribute, then also make sure that you have registered the AutoTx Facility. at Castle.Facilities.AutoTx.Lifestyles.PerTransactionLifestyleManagerBase.Resolve(CreationContext context) in d:\Builds\Castle.Transactions-beta\src\Castle.Facilities.AutoTx\Lifestyles\PerTransactionLifestyleManagerBase.cs:line 153 at Castle.Facilities.AutoTx.Lifestyles.WrapperResolveLifestyleManager`1.Resolve(CreationContext context) in d:\Builds\Castle.Transactions-beta\src\Castle.Facilities.AutoTx\Lifestyles\WrapperResolveLifestyleManager.cs:line 143 at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired) at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context, Boolean instanceRequired) at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context) at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments) at Castle.MicroKernel.DefaultKernel.Resolve(Type service, IDictionary arguments) at Castle.Facilities.TypedFactory.TypedFactoryComponent.Resolve(IKernel kernel) at Castle.Facilities.TypedFactory.Resolve.Invoke(IInvocation invocation) at Castle.Facilities.TypedFactory.TypedFactoryInterceptor.Intercept(IInvocation invocation) at Castle.DynamicProxy.AbstractInvocation.Proceed() at Castle.Proxies.Func`1Proxy.Invoke() at IntegrationTest.NCVIB.WindsorIoC.LocalDbTest.get_Reader() in D:\Projects\NCVIB-GIT\NCVIB\src\IntegrationTest.NCVIB\WindsorIoC\LocalDbTest.cs:line 22 at IntegrationTest.NCVIB.InspectionObjectMapTests.ReadWrite() in D:\Projects\NCVIB-GIT\NCVIB\src\IntegrationTest.NCVIB\InspectionObjectMapTests.cs:line 34
Here's a compilation of the setup calls I'm making (They're actually spread out across several different installers):
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>(); }
}
}
最佳答案
事实证明,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();
}
关于nhibernate - 使用 CaSTLe.Facilities.AutoTx 运行 NHibernate 时出现 MissingTransactionException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6439213/