Nhibernate Flush works提交不';T

Nhibernate Flush works提交不';T,nhibernate,Nhibernate,抱歉,如果我的问题没有太多细节,但我是nhibernate的新手,所以不知道如何表达。我想知道为什么在web应用程序中调用sessionflush不会抛出错误,而Commit会抛出错误 我通常有以下代码: session.SaveOrUpdate(item); session.Flush(); 但是如果我调用session.Commit(),我会得到一个具有相同标识符值的不同对象已经与session关联了 提交和刷新的工作原理不一样吗?似乎是因为我使用了FlushMode.Commit而不是F

抱歉,如果我的问题没有太多细节,但我是nhibernate的新手,所以不知道如何表达。我想知道为什么在web应用程序中调用sessionflush不会抛出错误,而Commit会抛出错误

我通常有以下代码:

session.SaveOrUpdate(item);
session.Flush();
但是如果我调用session.Commit(),我会得到一个具有相同标识符值的不同对象已经与session关联了


提交和刷新的工作原理不一样吗?

似乎是因为我使用了FlushMode.Commit而不是FlushMode.Auto。无法100%确定在以下情况下,为什么会在场景中引发您正在经历的
UnonqueObjectException

  • 调用当前ISession实例以按id获取,例如,
    .get(id)
    ,它保留对该项A的引用
  • 调用相同的ISession实例来持久化(
    SaveOrUpdate
    )项B
    ,并且
    • 这两个项具有相同的键(
      itemA.ID==itemB.ID
    • 两者都是不同的引用(
      itemA!=itemB
因此,如果发生这种情况,将抛出
ununiqueObjectException
(“具有相同标识符的不同对象…”)

Flush()
及其通过
FlushMode
的配置是分离持久层概念的实现。我们正在与一个
会话
进行工作/交互,调用
读取
操作(大部分是立即执行的或从缓存中提供的),调用
写入
操作-这些操作是排队的未执行将插入、更新、删除发布到数据库引擎中

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

发表声明的顺序:

  • 使用
    ISession.Save()
  • 所有实体更新
  • 所有集合删除
  • 所有集合元素的删除、更新和插入
  • 所有集合插入
  • 所有实体删除,使用
    ISession.Delete()
最后,这是枚举的一个片段,它确实配置了
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
}
///表示刷新策略。
/// 
///flush进程通过检测状态来同步数据库状态和会话状态
///更改和执行SQL语句
/// 
[可序列化]
公共枚举刷新模式
{
/// 
///未指定刷新模式的特殊值(如Java中)。
/// 
未指定=-1,
/// 
///除非明确指定Flush(),否则不会刷新ISession
///由应用程序调用。此模式对于只读非常有效
///交易
/// 
从不=0,
/// 
///调用Transaction.Commit()时,ISession将被刷新
/// 
提交=5,
/// 
///有时在执行查询之前刷新ISession,以便
///确保查询永远不会返回过时状态。这是默认的刷新模式。
/// 
自动=10,
/// 
///在每次查询之前刷新。这是
///几乎总是不必要和低效的。
/// 
始终=20
}

非常彻底和权威的回答。现在唯一奇怪的是,如果我设置FlushMode.Auto,我在执行session.Transaction.Commit时不会出现该错误,但在执行FlushMode.Never时,调用session.Flush(),然后执行session…Commit,我会出现错误。你知道为什么吗?一般来说,我强烈建议:在提交之前使用1)提交或2)从不使用显式Flush()。写入操作应位于一个会话中,读取操作应位于另一个会话中(例如,不同的web请求)。是否应该提交整个操作。因此,汽车通常不是最好的方式。我会说。我一直在使用“永不”和“显式”刷新。。。