Vegar
Vegar

Reputation: 12898

nHibernate: Fails to rollback complete operation

We have a userobject split between two tables, a person table and user table.

public UserMap() 
{
   Table("Person");
   Id(x => x.PersonId, "PersonId");
   Map(x => x.Name, "Name");

   Join("User", s => {
      s.Fetch.Join();
      s.KeyColumn("PersonId");
      s.Map(x => x.Username, "Username");
      s.Map(x => x.Password, "Password");
   });
}

When doing a insert, nHibernate will first insert Name into the Person table, and then Username and Password into the User table.

The problem arise when the insertion into the User-table fails (like trying to insert a user with a username that is already taken). The transaction fails, but the insertion into the Person table is not rolled back.

    public User Save(User user)
    {
        var session = SessionHelper.GetCurrent();
        using (var dbTransaction = session.BeginTransaction())
        {
            try
            {
                session.SaveOrUpdate(user);
                dbTransaction.Commit();
            }
            catch (Exception)
            {

                dbTransaction.Rollback();
                throw;
            }                
        }

        return user;
    }

Our SessionFactory is also set up with Fluent NHibernate

    public ISessionFactory BuildSessionFactory(string connectionString)
    {
        return Fluently.Configure().Database(OracleClientConfiguration.Oracle10.ConnectionString(c => c.Is(connectionString))
                                             .Provider<OracleDriverConnectionProvider>()
                                             .Driver<OracleDataClientDriver>()
                                             .ShowSql)
                                             .Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserMap>())
                                             .BuildSessionFactory();
    }

I have put the logfile from a failing session in a gist. The User entity is a little more complex in real life, and there are some authentication stuff going on, so the log file want match 1:1 with the painted picture...

Upvotes: 1

Views: 1707

Answers (3)

Suh
Suh

Reputation: 59

Instead of closing the session, you can use session.Clear() after you have roleld back the transaction, which will remove all pending writes and make session as good as new. That did the trick for my application.

Upvotes: -1

Jugal Panchal
Jugal Panchal

Reputation: 1548

Add User object in Person Object and Save Person Object only. Use Cascade.All() in Mapping file. or Second option is use TransactionScope.

Upvotes: 0

Tor
Tor

Reputation: 46

Seems like a similar problem was solved here. NHibernate will not revert you changes in the session when you rollback your transaction, i.e if you flush your session after the rollback, you will experience the problems you describe. To ensure no changes in your entities, when you rollback, you have to also close the session.

Upvotes: 3

Related Questions