.net 如何防止在使用Castle ActiveRecord/NHibernate刷新时将对象更改写入数据库

.net 如何防止在使用Castle ActiveRecord/NHibernate刷新时将对象更改写入数据库,.net,nhibernate,castle-activerecord,.net,Nhibernate,Castle Activerecord,NHibernate的默认行为是在调用Session.Flush()时将对对象的所有更改写入数据库。不管你愿不愿意,它都会这样做 当我们需要验证业务规则或输入等操作时,如何防止向数据库写入错误数据 例如 客户名称不为空 用户打开web浏览器(不带javascript)并删除客户名称 点击更新 Customer.Name属性已更新并 调用Customer.IsValid() 即使IsValid()为false并显示错误消息,NHibernate仍会更新数据库 使用ISession.execute

NHibernate的默认行为是在调用Session.Flush()时将对对象的所有更改写入数据库。不管你愿不愿意,它都会这样做

当我们需要验证业务规则或输入等操作时,如何防止向数据库写入错误数据

例如

  • 客户名称不为空
  • 用户打开web浏览器(不带javascript)并删除客户名称
  • 点击更新
  • Customer.Name
    属性已更新并
  • 调用
    Customer.IsValid()
  • 即使
    IsValid()
    为false并显示错误消息,NHibernate仍会更新数据库
使用ISession.execute(ObjectToEvent)方法来逐出无效对象

见: 和

您也可以使用FlushaAction.Never会话。即:

SessionScope session = new SessionScope(FlushAction.Never);
这会将默认行为从自动保存所有内容切换到显式需要对实体调用.Save()的对象。所以你可以做任何你需要做的验证,然后才保存你想要的

NHibernate的默认行为是在调用Session.Flush()时将对对象的所有更改写入数据库。不管你愿不愿意,它都会这样做

如果您不希望NHibernate刷新会话,那么为什么要让它刷新会话
Flush()
将对象写入数据库()的缩写

当我们需要验证业务规则或输入等操作时,如何防止向数据库写入错误数据

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

特别针对ActiveRecord:如果您自己不更改SessionScope,AR默认为每次调用会话的会话管理模式,其中为ActiveRecordMediator的每次操作创建一个新会话。因此,一旦检索到所有对象,它们就已经从父会话断开连接。除非调用Save(或SaveAndUpdate,甚至Update),否则更改不会被持久化。在每次调用的会话模式中,Save将创建会话,将要保存的对象附加到该会话,调用Save,然后处置会话(导致刷新,从而写入更改)

当您以这种方式使用AR时,它会完全满足您的需求(即除非您显式调用Save,否则不会写回任何更改)。但是这明显违背了预期的NHibernate行为,并且您不能进行延迟加载或从缓存中获得更多的使用。我曾在一些Web应用程序中使用过这种模式,但它们是预先设计好的,用于快速加载,而且相当多的持久对象实际上是不可变的和静态的,可以在启动时大量加载并缓存,而无需连接到任何会话。如果你的应用程序不适合这种模式,那么每次通话会话可能是个坏主意


因为您似乎正在使用UOW模式,所以不能利用这种行为。因此,您必须将对象从NHibernate会话中逐出(并且访问真正的ISession实例实际上并不像AR中看起来那么容易),或者更改应用程序的工作方式,以便在验证业务规则之前不会修改持久化对象的属性。

,我知道这完全是矫枉过正,但下面是我如何修复它的

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


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

Save并不意味着“保存更改”。更改会自动保存在后台(Flush就是这样做的)。保存将对象的状态从瞬态更改为持久性,并按照对象映射的指示将更改级联;它不一定立即执行SQL。我在web应用程序中使用它,因此我没有直接访问会话的权限(它由工作单元处理)。同意,这是可行的,但是我在我的客户端代码中调用了execute。不理想。此应用程序是web应用程序,会话由工作单元处理。它在每次web请求后自动刷新。您建议我如何验证我的业务对象?给出的示例很简单,但是,如果不创建对象,则其他示例更难验证。请在调用时验证所有数据和操作,以便属性不会更改为任何无效的内容。NHibernate的比喻很简单——内存中的持久对象和数据库中的数据应该被认为是可插入的;改变一个==改变另一个。忽略管道。