如何防止使用Castle ActiveRecord/NHibernate刷新数据库上的对象更改

问题描述:

NHibernate的默认行为是在调用Session.Flush()时将所有对对象的更改写入数据库。它可以做到这一点,不管你是否愿意。如何防止使用Castle ActiveRecord/NHibernate刷新数据库上的对象更改

当我们需要执行诸如验证业务规则或输入的操作时,我们如何防止将错误数据写入数据库?

例如..

  • 客户名称不为空。
  • 用户打开网页浏览器(不含javascript)并删除客户名称。
  • 点击更新。
  • Customer.Name property is updated and ..
  • Customer.IsValid()被调用。
  • 即使IsValid()为假,我们显示错误消息NHibernate仍然更新数据库。

具体ActiveRecord的:如果你不将自己SessionScope,AR默认改变的session-per-通话,这样的ActiveRecordMediator的每个操作创建一个新的会话的会话管理模式。因此,一旦检索到对象,您检索到的所有对象都已与父会话断开连接。直到/除非您调用Save(或SaveAndUpdate,甚至更新),否则更改将不会持续,除非您在每次调用会话模式时创建会话,将保存的对象附加到该会话,调用Save并且然后处理会话(导致刷新并因此写入更改)。

当你以这种方式使用AR时,它完全符合你的想法(即,除非明确地调用Save,否则不会写回任何更改)。但是这明显违背了期望的NHibernate行为,并且您不能进行延迟加载或从缓存中获得太多用处。我在一些Web应用程序中使用了这种模式,但是它们被预先设计用于急切加载,并且相当多的持久对象实际上是不可变的,并且是静态的,并且可以在启动时被en-masse加载并缓存而没有与任何连接会话。如果你的应用程序不适合这种模式,那么每次通话会话可能是一个坏主意。

由于您似乎正在使用UOW模式,因此无法利用此行为。因此,您必须从NHibernate会话中逐出对象(并且可以访问真正的ISession实例并不像在AR中那样容易),或者改变应用程序的工作方式,以便实际上未修改持久对象的属性直到您的业务规则得到验证之后。

使用ISession.Evict(objectToEvict)方法来驱逐无效对象。

参见:http://www.tobinharris.com/2007/2/3/nhibernate-faqhttp://www.surcombe.com/nhibernate-1.2/api/html/M_NHibernate_ISession_Evict.htm

+1

表示同意,这有效,但随后我打电话驱逐我的客户端代码。不理想。 – 2008-11-22 13:40:39

你也可以使用一个会话与FlushAction.Never。即:

SessionScope session = new SessionScope(FlushAction.Never); 

这将从所有自动保存到你需要明确在你的实体调用.Save()交换机的默认行为。所以你可以做任何你需要做的验证,然后只保存你想要的内容...

+2

保存并不意味着“保存更改”。更改会自动保存在幕后(这就是Flush所做的)。保存将对象的状态从瞬态更改为持久性,并按照对象映射的指示级联更改;它不一定立即执行SQL。 – yfeldblum 2008-11-22 05:17:37

+0

我在Web应用程序中使用它,所以我没有直接访问会话(它由工作单元处理)。 – 2008-11-22 13:41:27

NHibernate的默认行为是当Session.Flush()被调用时写入对象到数据库的所有更改。它可以做到这一点,不管你是否愿意。

如果你不想让NHibernate刷新会话,那你为什么要告诉它刷新会话? Flush()WriteAllChangesToObjectsToTheDatabase()的简写。

当我们需要做一些事情来验证业务规则或输入时,我们该如何防止将错误的数据写入数据库?

  • 验证变更之前修改模型对象。不要让内存中存在无效的模型对象(从模型公开的角度来看,不包括多线程场景)。
  • 将您的更改包装在一个事务中,如果您的模型对象验证失败(为什么您首先允许无效的模型对象?),这将会失败。

所以,我知道这是完全矫枉过正,但这里是我如何修复它。

转换为NHibernate 2.0并使用NHibernate Validator项目来运行我的输入验证规则。我还没有处理业务规则,但我认为我可以使用自定义的验证规则来完成这些规则,如果这不起作用,我可以使用nhibernate事件。

因为我已经在使用存储库模式,所以转换非常简单。它只需要大约4-5个小时,我们的模型非常广泛。能够从AR属性生成.xml文件是一个巨大的节省时间。