【问题标题】:Nhibernate Flush works commit doesn'tNhibernate Flush 作品提交不
【发布时间】:2014-03-25 13:34:40
【问题描述】:

对不起,如果我的问题没有太多细节,但我是 nhibernate 的新手,所以不知道如何表达。我想知道为什么在 Web 应用程序中调用会话刷新不会引发错误,但 Commit 会。

我正常有这个代码:

session.SaveOrUpdate(item);
session.Flush();

但是如果我调用 session.Commit() 我会得到 a different object with the same identifier value was already associated with the session 错误

Commit 和 Flush 的工作方式不同吗?

【问题讨论】:

    标签: nhibernate


    【解决方案1】:

    您正在经历的NonUniqueObjectException 在以下情况下被抛出:

    • 当前 ISession 实例被调用以通过 id 获取,例如.Get<TEntity>(id),并且一直引用这个item A
    • 相同 ISession 实例被调用以持久化 (SaveOrUpdate) 项目 B
      • 两个项目具有相同的密钥 (itemA.ID == itemB.ID)
      • 两者都是不同的引用 (itemA != itemB)

    所以,如果发生这种情况,NonUniqueObjectException("a different object with the same identifier...") 会被抛出。

    Flush() 及其通过FlushMode 的配置是分离持久层概念的实现。我们正在与session 工作/交互,调用Read 操作(主要是立即执行或从缓存中提供),调用Write 操作-排队。 执行。 向数据库引擎发出 INSERT、UPDATE、DELETE。

    只有在调用Flush() 时,会话才会“同步”对数据库的更改。 (其中之一) 的优点是 NHibernate 可以管理写入语句的顺序。 见:

    9.6. Flush

    发表声明的顺序:

    • 所有实体插入,以相同的顺序使用ISession.Save()保存相应的对象
    • 所有实体更新
    • 所有集合删除
    • 所有集合元素的删除、更新和插入
    • 所有集合插入
    • 所有实体删除,使用ISession.Delete()删除相应对象的顺序相同

    最后,这是枚举 FlushMode 的 sn-p,它确实配置了 Flush() 调用:

    /// <summary> Represents a flushing strategy.</summary>
    /// <remarks>
    /// The flush process synchronizes database state with session state by detecting state
    /// changes and executing SQL statements
    /// </remarks>
    [Serializable]
    public enum FlushMode
    {
        /// <summary>
        /// Special value for unspecified flush mode (like <see langword="null" /> in Java).
        /// </summary>
        Unspecified = -1,
            /// <summary>
        /// The <c>ISession</c> is never flushed unless <c>Flush()</c> is explicitly
        /// called by the application. This mode is very efficient for read only
        /// transactions
        /// </summary>
        Never = 0,
            /// <summary>
        /// The <c>ISession</c> is flushed when <c>Transaction.Commit()</c> is called
        /// </summary>
        Commit = 5,
            /// <summary>
        /// The <c>ISession</c> is sometimes flushed before query execution in order to
        /// ensure that queries never return stale state. This is the default flush mode.
        /// </summary>
        Auto = 10,
            /// <summary>
        /// The <see cref="ISession"/> is flushed before every query. This is
        /// almost always unnecessary and inefficient.
        /// </summary>
        Always = 20
    }
    

    【讨论】:

    • 非常彻底和权威的答案。
    • 现在唯一奇怪的是,如果我设置 FlushMode.Auto,我在执行 session.Transaction.Commit 时不会收到该错误,但是当我执行 FlushMode.Never 时,调用 session.Flush( ),然后进行会话...提交,我得到了错误。你知道为什么吗?
    • 一般来说,我强烈建议:使用 1) Commit 或 2) 绝不要在 Commit 之前使用明确的 Flush()。写入操作应该在一个会话中进行,在另一个会话中读取(例如,不同的 Web 请求)。整个操作是否应该提交。因此,AUTO 不会是最好的选择。我会说。我长期使用从不显式的 Flush ...
    【解决方案2】:

    似乎是因为我有 FlushMode.Commit 而不是 FlushMode.Auto。不是 100% 确定原因

    【讨论】:

      猜你喜欢
      • 2010-10-21
      • 1970-01-01
      • 2011-08-06
      • 1970-01-01
      • 2011-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多