Средство автоматического управления транзакциями Castle не устраняет проблемы - PullRequest
0 голосов
/ 21 июля 2011

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

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

3 голосов
/ 24 июля 2011

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

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

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

Чтобы настроить / зарегистрировать мои компоненты в контейнере, я использую Установщики. Я настраиваю сам контейнер, используя XML, который ссылается на эти установщики, а также на любые средства (например, NHibernate-интеграция / ведение журнала и т. Д.). В любом случае, я полагаю, что это могла быть какая-то проблема с заказом, из-за которой мои компоненты могли быть зарегистрированы до транзакции. Поскольку такие компоненты, зарегистрированные до TransactionFacility, не были переданы в TransactionComponentInspector и, следовательно, не получили TransactionInterceptor, зарегистрированный в компоненте. Как только я понял это, я вручную настроил контейнер (с правильным порядком вещей), и все, казалось, работало !!!

Теперь я должен попытаться понять, как это сделать в моей конфигурации XML. Если я не могу, я думаю, что я дам это и пойду для быстрой конфигурации контейнера (например, в глобальном приложении Http).

[править] см. Ниже:

_container = New WindsorContainer()
' TransactionFacility must be registered before components.
_container.AddFacility(Of TransactionFacility)()
_container.Install(Configuration.FromXmlFile("Configs\services.xml"))
1 голос
/ 22 июля 2011

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

0 голосов
/ 23 июля 2011

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

...