nhibernate - 使用 CaSTLe.Facilities.AutoTx 运行 NHibernate 时出现 MissingTransactionException

标签 nhibernate transactions castle-windsor

我正在尝试使用 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/

相关文章:

c# - CaSTLe DynamicProxy 接口(interface)代理生成

NHibernate Future<T> 与 Get()

.net - 为什么事件处理程序只能在 IHttpModule 初始化期间绑定(bind)到 HttpApplication 事件?

mysql - 默认情况下,所有 knex 查询都在事务中运行吗?

mysql - 读取未提交并更新

c# - LINQ to SQL 和并发问题

c# - 如何在 CaSTLe.Windsor 中配置提供多个服务的单个组件实例?

.net - 使用 CaSTLe AutoTx Facility 和 NHibernate Facility 的交易

c# - 使用被忽略的属性的 QueryOver

nhibernate - 从数据库读取时,HasMany 关系导致 "Found shared references to a collection"