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...