Search code examples
hibernatenhibernatefluent-nhibernate

Revert a deleted instance in NHibernate session


I remove objects like below with NHibernate:

var obj = session.Get<MyModel>(some_guid);
session.Delete(obj);

The object is now transient, and MyModel object with id some_guid is flagged as deleted object in NHibernate session.

Later in my legacy app, I need to cancel the deletion of some objects deleted in the session. I tried workaround below but had no luck:

 var e = ((SessionImpl)session).PersistenceContext.EntityEntries;
 var allEntities = e.Keys.Cast<object>().ToList();
 var item = allEntities.FirstOrDefault(c => c.Id == some_guid);
 session.Refresh(item); // throw an exception

The workaround above will throw an exception nhibernate instance was not in a valid state


Solution

  • The entity deletion is recorded in a action queue which can only be canceled by clearing the whole session (ISession.Clear).

    You cannot achieve what you are looking for. NHibernate does not support your scenario, canceling some pending changes in a session but not others.

    You could have tried ISession.Evict, but that causes a failure on Flush, because the action queue has then to act on an entity missing from the session persistence context. (It yields an exception guessing a threaded usage have been attempted but well, no, just an Evict on an entity having pending actions.)

    You have to change your application for avoiding having it deleting objects which should not be deleted in the first place.

    Or when detecting some objects which were deleted in the session should not be deleted, cancel the whole session (rollback the transaction, dispose the session, use a new one), and redo the work without deleting objects which must stay there. (If you do not use a transaction, FlushMode.Auto may flush deletions before you Clear the session.)

    Or at worst, keep a copy of your objects, commit the session, and re-save them...