Castle 自动事务管理设施仍然存在问题
关于 Castle 自动交易管理设施;我在不刷新会话的情况下将操作实际保存到数据库时遇到一些困难。
我正在使用以下组件 * NHibernate.dll v3.1.0.4000 * Castle.Core.dll v2.5.2.0 * 城堡.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 模式。 (事务性)演示者服务的关键部分如下所示:
<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 和事务设施注册为如下:
<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 (遵循每个请求开放会话模式)会导致我的实体被持久化,但这似乎并没有发生......
Regarding the Castle Automatic Transaction Management Facility; I'm having some difficulties getting operations to actually save to the database without flushing the session.
I'm using the following components
* 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
I have followed the Castle documentation very closely and have not been able to resolve my issue.
My (web-)application follows the MVP pattern. The key parts of the (transactional) presenter-service are shown below:
<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
This presenter-service is registered in an installer:
container.Register( _
Component.For(Of CampusEditPresenter) _
.Interceptors(Of DebugLoggingInterceptor) _
.LifeStyle.Transient)
and resolved by the view (in the base):
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
I have registered the NHibernate and Transaction facilities in an XML configuration file as follows:
<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>
and I have registered the SessionWebModule Http module in my Web.config:
<httpModules>
<add name="NHibernateSessionWebModule" type="Castle.Facilities.NHibernateIntegration.Components.Web.SessionWebModule, Castle.Facilities.NHibernateIntegration"/>
...
</httpModules>
Any ideas as to why this may not be working?
I can get everything working when I a) instansiate my own transactions from the ISession instance and maually commit these transactions, or if I b) use the Automatic Transaction Management AOP-mechanism AND manuall flush the session instance (though I shouldn't have to manually do this).
I would have also thought that SessionWebModule IHttpModule (which follows the open-session-per-request pattern) would cause my entities to be persisted, but this doesnt seem to be happening...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
所以我发现 TransactionInterceptor 没有在我的组件上注册。
从 github 下载 Castle.Facilities.AutomaticTransactionManagement 源代码并逐步执行后,我发现了我的问题并设法解决了它。
基本上,TransactionFacility 向 ComponentModelBuilder 添加了一个贡献者 TransactionComponentInspector,它允许在构建组件时进行一些额外的配置贡献。对于 TransactionComponentInspector,它会在组件上查找“Transactional”类属性,如果存在,它将在组件上注册一个 TransactionInterceptor。然而,我的组件从未得到 TransactionComponentInspector 的贡献。
为了在容器上配置/注册我的组件,我使用安装程序。我使用 XML 配置容器本身,它引用这些安装程序以及任何设施(例如 NHibernate 集成/日志记录等)。无论如何,我相信这可能是某种订购问题,我的组件可能已经在交易设施之前注册。由于在 TransactionFacility 之前注册的此类组件没有得到 TransactionComponentInspector 的贡献,因此没有在组件上注册 TransactionInterceptor。一旦我意识到这一点,我就手动配置了容器(使用正确的顺序),一切似乎都正常!
现在我必须尝试找出如何在 XML 配置中执行此操作。如果我不能,我想我会转储它并进行容器的流畅配置(例如在全局 HttpApplication 中)。
[编辑]见下:
So I worked out the TransactionInterceptor was not getting registerd on my components.
After downloading the Castle.Facilities.AutomaticTransactionManagement source from github and stepping through, I found my issue and managed to resolve it.
Basically the TransactionFacility adds a contributor, TransactionComponentInspector, to the ComponentModelBuilder, which allows for some additional configuration contribution whilst building the component. In the case of the TransactionComponentInspector, it looks for a "Transactional" class attribute on the component and if it exists it will register a TransactionInterceptor on the component. However, my components were never getting contributed to by the TransactionComponentInspector.
To configure/register my components on the container, I use Installers. I configure the container itself using XML, which references these installers as well as any facilities (e.g. NHibernate-integration/logging etc.). Anyways, I believe it may have been some kind of ordering issue whereby my components might have been getting registered before the transaction facility. As such components registered before the TransactionFacility were not getting contributed-to by the TransactionComponentInspector and were therefore not getting a TransactionInterceptor registered on the component. Once I realised this I manually configured the container (with the correct order of things) and everything seemed to work!!!
Now I've got to try and work out how to do this in my XML configuration. If I can't, I guess I'll dump this and go for fluent configuration of the container (e.g. in the global HttpApplication).
[edit] see below:
我也经历过非常相似的行为。原来我正在创建一个 Logging Aspect Interceptor。我创建了一个默认拦截器选择器,以便我可以在需要的地方应用日志记录。在这样做的过程中,我搞乱了 TransactionalInterceptor。一旦我删除了默认拦截器选择器,事务就开始工作。
I was experiencing very similar behavior. It turned out that I was creating a Logging Aspect Interceptor. I had created a Default Interceptor Selector so that I could apply logging where needed. In doing this, I was messing up the TransactionalInterceptor. Once I removed the Default Interceptor Selector, the Transactions started working.
尝试 SwampyFox 的建议,如果这不能解决您的问题,还可以尝试 3.0.x 的 Tx、AutoTx 和 NHibFac 的 nuget。新的开发(如果它是一个错误)正在研究这些。 Tell是尝试Foxy建议的结果。
Try SwampyFox's suggestion, then also try the nuget of 3.0.x of Tx, AutoTx and NHibFac, if that doesn't solve your problems. New development (if it's a bug) is going into those. Tell is the result of trying Foxy's suggestion.