Reputation: 1633
Sorry if my question doesn't have much detail but I'm new to nhibernate so not sure how to phrase. I'm wondering why calling session flush in a web application would not throw an error but Commit would.
I have this code normally:
session.SaveOrUpdate(item);
session.Flush();
but if I call session.Commit() I get a different object with the same identifier value was already associated with the session
error
Doesn't Commit and Flush work the same?
Upvotes: 1
Views: 1042
Reputation: 123861
The NonUniqueObjectException
, you are experiencing, is thrown in scenarios, when:
.Get<TEntity>(id)
, and it keeps reference to this item ASaveOrUpdate
) an item B and
itemA.ID == itemB.ID
)itemA != itemB
)So, if this happens, the NonUniqueObjectException
("a different object with the same identifier...") is thrown.
The Flush()
and its configuration via FlushMode
is the implementation of the concept of the detached persistence layer. We are working/interacting with a session
, calling Read
operations (mostly executed immedietly or provided from cache), calling Write
operations - which are queued. Not executed. No INSERT, UPDATE, DELETE is issued into DB engine.
Only when the Flush()
is called, the session does the "synchronization" of the changes to DB. The advantage (one of many) is that NHibernate can manage the order of the write statements. See:
The order of issued statements:
ISession.Save()
ISession.Delete()
And finally, this is a snippet of the enum FlushMode, which does configure the Flush()
call:
/// <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
}
Upvotes: 3
Reputation: 1633
Seems to be because I had FlushMode.Commit and not FlushMode.Auto. Not 100% sure why
Upvotes: 0