This started out as a support question, but it is an interesting enough (and general enough) that I think it is important to make sure that it is recorded.

When working with detached entities (from another session), sometimes, at seemingly random places, NHibernate will throw a NonUniqueObjectException. Where it actually happen and the exact cause depend on several variables, but the root problem is simple: working with detached entities safely requires that you be aware of possible identity map violations.

// opps, user instance with the same id but with different// reference was detected session.SaveOrUpdate(post);

tx.Commit();}

The reason that the problem seems obscure at first is that there are quite a few variables that are going to affect how this will behave. In order to reproduce the issue you need:

An association that is marked with a cascade option, such as “save-update”, “all” or “all-delete-orphan”

The entity this association points needs to be loaded in the second session.

Depending on what you are doing (saving an entity vs. updating it) and what the options are for the id generation, you may get the error on the SaveOrUpdate or on the Commit.

The actual details are pretty unimportant, but understanding what is going on is. The issue is that NHibernate has been asked to perform something that violate one of its core assumptions, break the identity map.

Because of the cascade options set on Post.User, we are asking NHibernate to also save the User instance associated with the post. The problem is that when NHibernate is encountering that, it is going to see an entity with an id that is already on the session but as a different reference. That violates the identity map rules and force NHibernate to throw an exception.

The root cause is, as I mentioned, trying to work with a detached entity as if it was a regular entity. NHibernate provides a different API for working with detached entities safely, precisely because of those sort of reasons.

The appropriate way of handling such an issue is to use the Merge method, which will take a detached object graph and merge it into the session, properly resolving such conflict. Note, however, that Merge will return a different entity instance than the one that you passed.

What is the downside of using session.Lock(item, LockMode.None) for associating item with session?

I ask because I have the folowing scenario:

I have to delete a few trees of items,when each item may belong to more then one tree. Merging each item into session means I will have to traverse all the trees and replace all instances of old item with new item. Will the session.Lock have unintended side effects?