【问题标题】:Why is NHibernate saving objects when I never execute session.Save?当我从不执行 session.Save 时,为什么 NHibernate 会保存对象?
【发布时间】:2011-07-17 21:59:43
【问题描述】:

我正在使用 NHibernate 和 Fluent NHibernate。

我有启动事务的代码,然后我进入一个创建多个对象的循环。对于每个对象,我都会检查某些条件。如果满足这些条件,那么我对对象执行 session.SaveOrUpdate()。在循环结束时,我发出一个提交事务。

我在 session.SaveOrUpdate 命令上设置了一个断点,证明它从未达到(因为条件没有被任何对象满足环形)。 然而,当事务被提交时,对象被保存了!

我正在使用 AuditInterceptor 并在 OnSave 方法中设置了一个断点。它正在被调用,但堆栈跟踪仅追溯到提交事务的语句。

此时没有任何类型的对象对其执行了 SaveOrUpdate,因此级联无法解释它。

NHibernate 为什么要保存这些对象?

【问题讨论】:

    标签: nhibernate fluent-nhibernate


    【解决方案1】:

    来自NHibernate ISession.Update线程:

    这是normaldefault behavior

    Hibernate 维护一个对象缓存 已插入、更新或 删除。它还维护一个缓存 已查询的对象 数据库。这些对象是 被称为持久对象 只要 EntityManager 是 用于获取它们的仍然处于活动状态。 这意味着任何更改 范围内的这些对象 交易是自动的 事务进行时持久化 坚定的。这些更新是隐式的 交易范围内 而且您不必显式调用 任何持久化值的方法。

    来自Hibernate Pitfalls part 2

    Q) 我还需要保存吗? 更新内部交易?

    Save() 只需要 不是持久的(例如新的 对象)。您可以使用更新带来 已被驱逐的对象 进入会话。

    来自NHibernate's automatic (dirty checking) update behaviour

    我刚刚发现,如果我得到一个 来自 NHibernate 会话的对象和 更改对象的属性, NHibernate 会自动更新 在没有我的情况下提交的对象 调用 Session.Update(myObj)!

    答案:您可以将 Session.FlushMode 设置为 FlushMode.Never。这将使您的 显式操作,即:在 tx.Commit() 或 session.Flush() 上。 当然,这仍然会更新 提交/刷新时的数据库。如果你这样做 不想要这种行为,然后打电话 session.Evict(yourObj) 它会 然后变成瞬态和 NHibernate 不会为它发出任何 db 命令。

    【讨论】:

    • 根据上面的说法,“Save() 只需要非持久化的对象(比如新对象)。”正在保存的有问题的对象新对象,但是代码确实与现有对象建立了关系,所以也许这就是它被保存的原因。
    • 看来我需要专门驱逐我不想要的那些,并且可能还将 FlushMode 设置为从不。我会试一试...
    • 看起来不会那么简单。我不想保存的对象在构造函数中引发异常。所以我指向新对象的指针为空。由于我不能使用 session.Evict(null) 来驱逐对象,NH 仍然保存它。我捕获异常并记录它,但我不想终止该进程。我也不想回滚事务,因为出于性能原因我每个事务处理 100 个对象,并且我需要保留和持久化事务中的任何有效对象。
    【解决方案2】:

    这与会话刷新模式为 FlushMode.Commit(默认)有关。提交事务后,对会话中对象所做的任何更改都会保存并保持不变。

    您可以设置会话的 FlushMode 属性。如果您想要一个只读事务,请指定 FlushMode.Manual。

    希望这会有所帮助!

    【讨论】:

    • 谢谢,Sammo,这确实有帮助。我需要的不是只读事务。我需要能够在事务中创建多个对象并选择性地只保存其中的一些。
    • 可能您可以更改父集合上的级联以不保存/更新...我希望您可以在要保留的单个子对象上调用“保存”。但我会小心,因为更改级联行为可能会对其他地方产生影响!
    • 我不想搞乱级联行为。这会导致其他问题。此外,由于我需要保存事务中的其他对象,我仍然需要执行刷新,无论是手动还是自动。当我这样做时,我仍然会遇到保存不需要的对象的问题。控制刷新时间不会改变这一点。正如下面 binaryhowl 所建议的那样,使用 session.Evict(object) 驱逐不需要的对象似乎是防止它们被保存的唯一方法。 (我的情况仍然存在问题,正如我在我的 cmets 在他的帖子中指出的那样。)
    猜你喜欢
    • 2017-07-10
    • 1970-01-01
    • 2012-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多