代码之家  ›  专栏  ›  技术社区  ›  Kyle West

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

  •  2
  • Kyle West  · 技术社区  · 16 年前

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

    例如。。

    • 客户名称不为空。
    • 用户打开web浏览器(不带javascript)并删除客户名称。
    • Customer.Name 属性已更新,并且。。
    • Customer.IsValid() 被称为。
    • 即使 IsValid() 为false,我们显示错误消息NHibernate仍在更新数据库。
    5 回复  |  直到 16 年前
        1
  •  2
  •   Neil Hewitt    16 年前

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

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

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

        2
  •  2
  •   Nathan    16 年前
        3
  •  1
  •   yfeldblum    16 年前

    如果您不希望NHibernate刷新会话,那么为什么要让它刷新会话? Flush() WriteAllChangesToObjectsToTheDatabase()

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

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

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

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

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

        5
  •  0
  •   KevinT    16 年前

    您还可以将会话与FlushAction.Never一起使用。即:

    SessionScope session = new SessionScope(FlushAction.Never);