Средство автоматического управления транзакциями Castle не устраняет проблемы

Относительно Замка Автоматическое Средство Управления Транзакциями; У меня возникают некоторые трудности с получением операций для фактического сохранения в базе данных без очистки сеанса.

Я использую следующие компоненты * 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

Я очень внимательно следил за документацией Замка и не смог решить мою проблему.

Мое (веб-) приложение следует шаблону 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

Я зарегистрировал средства NHibernate и Transaction в файле конфигурации XML следующим образом:

<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>

и я зарегистрировал модуль SessionWebModule Http в моем Web.config:

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

Есть идеи, почему это может не сработать?

Я могу заставить все работать, когда я а) создаю свои собственные транзакции из экземпляра ISession и вручную фиксирую эти транзакции, или если я б) использую AOP-механизм автоматического управления транзакциями и вручную очищаю экземпляр сеанса (хотя мне не нужно было этого делать) сделать это вручную).

Я бы также подумал, что SessionWebModule IHttpModule (который следует шаблону open-session-per-request) вызовет сохранение моих сущностей, но, похоже, этого не происходит...

3 ответа

Решение

Поэтому я решил, что TransactionInterceptor не регистрируется на моих компонентах.

Загрузив исходный код Castle.Facilities.AutomaticTransactionManagement с github и пройдя по нему, я нашел свою проблему и смог ее решить.

По сути, TransactionFacility добавляет участника, TransactionComponentInspector, в ComponentModelBuilder, что позволяет вносить дополнительный вклад в конфигурацию при создании компонента. В случае TransactionComponentInspector он ищет атрибут компонента "Transactional" в компоненте и, если он существует, он регистрирует TransactionInterceptor в компоненте. Тем не менее, мои компоненты никогда не были добавлены TransactionComponentInspector.

Чтобы настроить / зарегистрировать мои компоненты в контейнере, я использую Установщики. Я настраиваю сам контейнер, используя XML, который ссылается на эти установщики, а также на любые средства (например, NHibernate-интеграция / ведение журнала и т. Д.). В любом случае, я полагаю, что это могла быть какая-то проблема с заказом, из-за которой мои компоненты могли быть зарегистрированы до транзакции. Поскольку такие компоненты, зарегистрированные до 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"))

Я испытывал очень похожее поведение. Оказалось, что я создавал перехватчик аспекта протоколирования. Я создал селектор перехватчиков по умолчанию, чтобы при необходимости можно было вести журналы. При этом я испортил TransactionalInterceptor. Как только я удалил Селектор Перехватчика по умолчанию, Транзакции начали работать.

Попробуйте предложение SwampyFox, а затем попробуйте Nuget 3.0.x Tx, AutoTx и NHibFac, если это не решит ваши проблемы. Новые разработки (если это ошибка) входит в них. Скажите это результат попытки предложения Фокси.

Другие вопросы по тегам