【问题标题】:Castle Automatic Transaction Management Facility persist issuesCastle 自动事务管理工具持续存在问题
【发布时间】:2011-10-09 21:53:16
【问题描述】:

关于城堡自动交易管理设施;我在不刷新会话的情况下将操作实际保存到数据库时遇到了一些困难。

我正在使用以下组件 * 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 文档,但未能解决我的问题。

我的(网络)应用程序遵循 MVP 模式。 (事务性)presenter-service 的关键部分如下所示:

<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 机制并手动刷新会话实例(尽管我不应该不必手动执行此操作)。

我还认为 SessionWebModule IHttpModule(遵循 open-session-per-request 模式)会导致我的实体被持久化,但这似乎没有发生......

【问题讨论】:

    标签: nhibernate transactions aop castle castle-autotx


    【解决方案1】:

    所以我发现 TransactionInterceptor 没有在我的组件上注册。

    在从 github 下载 Castle.Facilities.AutomaticTransactionManagement 源并逐步完成后,我发现了我的问题并设法解决了它。

    基本上,TransactionFacility 将贡献者 TransactionComponentInspector 添加到 ComponentModelBuilder,它允许在构建组件时进行一些额外的配置贡献。对于 TransactionComponentInspector,它会在组件上查找“Transactional”类属性,如果存在,它将在组件上注册一个 TransactionInterceptor。但是,我的组件从未得到 TransactionComponentInspector 的贡献。

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

    现在我必须尝试找出如何在我的 XML 配置中执行此操作。如果我不能,我想我会转储这个并进行容器的流畅配置(例如在全局 HttpApplication 中)。

    [编辑]见下文:

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

    【讨论】:

    • 我需要做的是在启动时从内核获取已经可用的处理程序并循环通过它们,检查 - 它已经在 v3 中计划好了。如果您有时间帮忙,我将非常感激 :)
    • 查看github.com/haf/Castle.Transactions 并针对develop 分支进行一些开发,发送拉取请求;)。
    【解决方案2】:

    我遇到了非常相似的行为。事实证明,我正在创建一个 Logging Aspect Interceptor。我创建了一个默认拦截器选择器,以便我可以在需要的地方应用日志记录。在这样做时,我搞砸了 TransactionalInterceptor。一旦我删除了默认拦截器选择器,事务就开始工作了。

    【讨论】:

    • 有趣的是,我们俩都在单步执行相同的代码。我开始怀疑注册顺序是否有问题。显然是的。对于未来的开发人员,请检查注册顺序以及错误实现的拦截器选择器:)
    【解决方案3】:

    尝试 SwampyFox 的建议,然后尝试 3.0.x 的 Tx、AutoTx 和 NHibFac 的 nuget,如果这不能解决您的问题。新的开发(如果它是一个错误)正在进入这些领域。 Tell 是尝试 Foxy 建议的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 2010-10-15
      • 2016-11-30
      • 2011-11-16
      • 1970-01-01
      • 2017-05-09
      相关资源
      最近更新 更多