I am facing an unusual behaviour with the Repository and Transactions and its making me mad.
I have two simple POCO classes Action and Version as follows. There is a one to many relationship from Action->Version.
public class Action : Entity
{
public virtual string Name
{
get;
set;
}
public virtual IList<Version> Versions
{
get;
protected set;
}
public Action()
{
Versions = new List<Version>();
}
public virtual void AddVersion( Version version )
{
version.Action = this;
Versions.Add( version );
}
}
public class Version : Entity
{
public virtual int Number
{
get;
set;
}
public virtual Action Action
{
get;
set;
}
public Version()
{
}
}
Now I have a code segment as follows:
var actionRep = new Repository<Action>();
var versionRep = new Repository<Version>();
var act1 = new Action( );
actionRep .SaveOrUpdate( act1 );
using (versionRep .DbContext.BeginTransaction())
{
var v1 = new Version();
act1.AddVersion( v1 );
//versionRep .SaveOrUpdate( v1 );
versionRep .DbContext.CommitTransaction();
}
In the above code I am just creating Action and Version repositories. First I persist an Action object using Action Repository. Then I begin a transaction using Version repository , create a new version, set references with the Action, and Commit the transaction without actually calling Version Repository.
The result is a bit strange. The version object gets persisted even though I have not called SaveOrUpdate method on version repository. If I comment out the line act1.AddVersion( v1 ); within the transaction, then the Version does not get persisted.
After a bit of struggle I tested the same scenario using NHibernate directly instead of using Sharp Architecture repositories using same fluent mapping/configuration (AutoPersistenceModelGenerator.Generate()). And The result is as expected. The version object does not get persisted. Here is the code
var sessionFactory = CreateSessionFactory();
_act1 = new Action();
using( var session = sessionFactory.OpenSession() )
{
session.SaveOrUpdate( _act1 );
}
using( var session = sessionFactory.OpenSession() )
{
using (var transaction = session.BeginTransaction())
{
_v1 = new Version();
_act1.AddVersion( _v1 );
//session.SaveOrUpdate( _act1 );
transaction.Commit();
}
}
The CreateSessionFactory() method is as follows. Nothing complicated
private const string _dbFilename = "nhib_auditing.db";
private static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database( SQLiteConfiguration.Standard
.UsingFile( _dbFilename )
.ShowSql())
.Mappings( m => m.AutoMappings.Add( new
AutoPersistenceModelGenerator().Generate() ) )
.ExposeConfiguration( BuildSchema )
.BuildSessionFactory();
}
Now If sombody could please let me know why I am having this behaviour. Its making me mad.
Just so that you know I have not overridden mapping for Action and Version either.
Awaiting Nabeel
This is the expected behavior if you have cascading operations declared in the mapping. When you called SaveOrUpdate
on act1 you made the transient object persistent; that is, NHibernate is tracking it and will save it when the session is flushed. Another way to make an object persistent is to associate it with a persistent object, as you did when you called act1.AddVersion( v1 );
. The session was flushed when the transaction was committed so v1 was saved. This article explains the details of working with persistent objects.