Search code examples
nhibernatesessiontransactionsrollback

NHibernate 3 session state after rollback()


I have a problem.

using (var tran = repository.Session.BeginTransaction())
{
    try
    {
        repository.Save(entity);
        tran.Comit();
    }
    catch(Exception)
    {
        tran.Rollback();
        throw;
    }    
}

using (var tran = repository.Session.BeginTransaction())
{
    try
    {
        repository.GetById(id);
        tran.Comit();
    }
    catch(Exception)
    {
        tran.Rollback();
        throw;
    }    
}

When I try to get an entity by ID after exception and tran.rollback() in the first using block, I get an update exception. So NHibernate is trying to update the entity from the first using block in the second using block.

Why? I did the tran.Rollback(). Must I do Session.Clear(), too?


Solution

  • According to Hibernate's API, when a Hibernate Session throws an exception, you must close the Session and create a new one. Also, when you roll back a Hibernate transaction, you must not later commit it or flush the Session - you must start over in a new Session.

    In particular (and this is an implementation detail so don't rely on it), after a rollback, the Hibernate Session still has entities created/modified since the transaction began - Hibernate doesn't go through your entities and revert all changes you made. Therefore, if you roll back the transaction and then flush the Session, Hibernate will commit entity changes that you thought you rolled back. If you are going to play with fire by trying to hack around this behavior (such as by clearing the Session), beware. It's best to just start over with a new Session.