关于城堡自动交易管理设施;我在运行实际保存到数据库而不刷新会话时遇到了一些困难。
我正在使用以下组件 * 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(遵循每个请求的开放会话模式)会导致我的实体被持久化,但这似乎不会发生......
答案 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的建议的结果。