城堡自动交易管理工具持续存在问题

时间:2011-07-21 04:04:13

标签: nhibernate transactions aop castle castle-autotx

关于城堡自动交易管理设施;我在运行实际保存到数据库而不刷新会话时遇到了一些困难。

我正在使用以下组件 * NHibernate.dll v3.1.0.4000 * Castle.Core.dll v2.5.2.0 * Castle.Windsor.dll v2.5.3.0 * Castle.Facilities.NHibernateIntegration.dll v1.1.0.0 * Castle.Services.Transaction.dll v2.5.0.0 * Castle.Facilities.AutoTx.dll v2.5.1.0

我非常密切地关注Castle文档,但无法解决我的问题。

My(web-)应用程序遵循MVP模式。 (交易)演示者服务的关键部分如下所示:

<Transactional()> _
Public Class CampusEditPresenter
    Inherits BasePresenter(Of ICampusEditView)

    Public Sub New(ByVal view As ICampusEditView)
        MyBase.New(view)
    End Sub

    ...

    <Transaction(TransactionMode.Requires)> _
    Public Overridable Sub Save() Implements ICampusEditPresenter.Save

        ' Simplified
        Using session As ISession = _sessionManager.OpenSession()

            Dim campus As New Campus()

            campus.Code = _view.Code
            campus.ShortDescription = _view.ShortDescription
            campus.LongDescription = _view.LongDescription
            campus.StartDate = _view.StartDate
            campus.EndDate = _view.EndDate

            session.Save(campus)

        End Using

    End Sub

End Class

此演示者服务已在安装程序中注册:

container.Register( _
    Component.For(Of CampusEditPresenter) _
    .Interceptors(Of DebugLoggingInterceptor) _
    .LifeStyle.Transient)

并由视图解决(在基础中):

Public Class BasePage(Of TPresenter)
    Inherits Page

    Protected _presenter As TPresenter

    ...

    Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Init
        _presenter = _container.Resolve(Of TPresenter)(New With {Key .view = Me})
    End Sub

    ...

End Class

Public Class CampusEdit
Inherits BasePage(Of CampusEditPresenter)
    Implements ICampusEditView

    ...

    Protected Sub btnSave_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSave.Click
        _presenter.Save()
    End Sub

    ...

End Class

我已在XML配置文件中注册了NHibernate和Transaction工具,如下所示:

<facility id="transaction" type="Castle.Facilities.AutoTx.TransactionFacility, Castle.Facilities.AutoTx" />
<facility id="nhibernate" type="Castle.Facilities.NHibernateIntegration.NHibernateFacility, Castle.Facilities.NHibernateIntegration" isWeb="true" configurationBuilder="[removed].AutoConfigurationBuilder, [removed]">
    <factory id="nhibernate.factory">
    <settings>
            <item key="connection.driver_class">NHibernate.Driver.OracleClientDriver, NHibernate</item>
      <item key="connection.connection_string">[removed]</item>
      <item key="show_sql">false</item>
      <item key="dialect">NHibernate.Dialect.Oracle10gDialect, NHibernate</item>
      <item key="query.substitutions">true 1, false 0, yes 'Y', no 'N'</item>
      <item key="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</item>
      <item key="current_session_context_class">web</item>
      <item key="hbm2ddl.keywords">auto-quote</item>
        </settings>
    </factory>
</facility>

我在Web.config中注册了SessionWebModule Http模块:

<httpModules>
    <add name="NHibernateSessionWebModule" type="Castle.Facilities.NHibernateIntegration.Components.Web.SessionWebModule, Castle.Facilities.NHibernateIntegration"/>
    ...
</httpModules>

关于为什么这可能不起作用的任何想法?

当我a)从ISession实例实现我自己的事务并实际提交这些事务时,或者如果我b)使用自动事务管理AOP机制和manuall刷新会话实例(虽然我不应该')必须手动执行此操作。)

我还认为SessionWebModule IHttpModule(遵循每个请求的开放会话模式)会导致我的实体被持久化,但这似乎不会发生......

3 个答案:

答案 0 :(得分:3)

所以我确定没有在我的组件上注册TransactionInterceptor。

从github下载Castle.Facilities.AutomaticTransactionManagement源并单步执行后,我发现了我的问题,并设法解决了这个问题。

基本上,TransactionFacility将一个贡献者TransactionComponentInspector添加到ComponentModelBuilder,这允许在构建组件时做出一些额外的配置贡献。在TransactionComponentInspector的情况下,它在组件上查找“Transactional”类属性,如果它存在,它将在组件上注册TransactionInterceptor。但是,我的组件永远不会被TransactionComponentInspector贡献。

要在容器上配置/注册我的组件,我使用安装程序。我使用XML配置容器本身,它引用了这些安装程序以及任何工具(例如NHibernate-integration / logging等)。无论如何,我认为这可能是某种订购问题,我的组件可能已在交易设施之前注册。因为在TransactionFacility没有得到TransactionComponentInspector的贡献之前注册的这些组件因此没有在组件上注册TransactionInterceptor。一旦我意识到这一点,我手动配置容器(具有正确的顺序),一切似乎都有效!!!

现在我必须尝试在我的XML配置中找出如何做到这一点。如果我不能,我想我会转储它并进行容器的流畅配置(例如在全局HttpApplication中)。

[edit]见下文:

_container = New WindsorContainer()
' TransactionFacility must be registered before components.
_container.AddFacility(Of TransactionFacility)()
_container.Install(Configuration.FromXmlFile("Configs\services.xml"))

答案 1 :(得分:1)

我遇到了非常相似的行为。原来我正在创建一个Logging Aspect Interceptor。我创建了一个默认拦截器选择器,以便我可以在需要的地方应用日志记录。在这样做时,我搞乱了TransactionalInterceptor。删除Default Interceptor Selector后,Transactions开始工作。

答案 2 :(得分:0)

尝试SwampyFox的建议,然后尝试使用3.0x的Tx,AutoTx和NHibFac,如果这不能解决您的问题。新的开发(如果它是一个bug)正在进入那些。 Tell是尝试Foxy的建议的结果。