NHibernate的默认行为是在调用Session.Flush()时将对象的所有更改写入数据库。无论你是否愿意,都可以这样做。
当我们需要执行验证业务规则或输入等操作时,我们如何防止将错误数据写入数据库?
例如..
Customer.Name
属性已更新并且.. Customer.IsValid()
被调用。 IsValid()
为false并且我们显示错误消息,NHibernate仍会更新数据库。答案 0 :(得分:2)
使用ISession.Evict(objectToEvict)方法驱逐无效对象。
请参阅:http://www.tobinharris.com/2007/2/3/nhibernate-faq 和 http://www.surcombe.com/nhibernate-1.2/api/html/M_NHibernate_ISession_Evict.htm
答案 1 :(得分:2)
特别针对ActiveRecord:如果您不自行更改SessionScope,AR默认为会话管理模式,每次调用会话,其中为ActiveRecordMediator的每个操作创建一个新会话。因此,检索后,您检索的所有对象都已与其父会话断开连接。除非您调用Save(或SaveAndUpdate,甚至更新),在每个通话会话模式中创建会话,将要保存的对象附加到该会话,调用保存,然后更改将不会保留更改。然后处理会话(导致刷新,从而写入更改)。
当你以这种方式使用AR时,它确实完全符合您的要求(即除非您明确调用Save,否则不会写回任何更改)。但是这显然违背了预期的NHibernate行为,并且你不能进行延迟加载或者从缓存中获得很多用处。我已经将这种模式用于某些Web应用程序,但它们是预先设计用于预先加载的,并且很多持久对象实际上是不可变的和静态的,并且可以在启动时集中加载并在没有任何连接的情况下进行缓存会话。如果您的应用不适合此型号,那么每次通话会话可能是一个坏主意。
由于您似乎使用的是UOW模式,因此无法利用此行为。因此,您必须从NHibernate会话中逐出对象(并且访问真正的ISession实例实际上并不像AR中那样容易),或者更改应用程序的工作方式,以便实际上不修改持久对象的属性直到您的业务规则得到验证之后。
答案 2 :(得分:1)
NHibernate的默认行为是在调用Session.Flush()时将对象的所有更改写入数据库。无论你是否愿意,都可以这样做。
如果您不希望NHibernate刷新会话,那么为什么要告诉它刷新会话? Flush()
是WriteAllChangesToObjectsToTheDatabase()
的缩写。
当我们需要执行验证业务规则或输入等操作时,我们如何防止将错误数据写入数据库?
答案 3 :(得分:1)
所以,我知道这完全是矫枉过正,但这就是我修复它的方法。
转换为NHibernate 2.0并使用NHibernate Validator项目来运行我的输入验证规则。我还没有处理业务规则,但我认为我可以使用自定义验证器规则来执行它们,如果这不起作用,我可以使用nhibernate事件。
由于我已经在使用存储库模式,因此转换非常简单。它只需要4-5个小时,我们的模型相当广泛。能够从AR属性生成.xml文件节省了大量时间。
答案 4 :(得分:0)
您也可以使用具有FlushAction.Never的会话。即:
SessionScope session = new SessionScope(FlushAction.Never);
这将切换默认行为,自动将所有内容保存到您明确需要在实体上调用.Save()。所以你可以做任何你需要做的验证,然后保存你想要的......