Fluent NHibernate, Castle Windsor, and Automatic Transactions

Getting things hooked up

I recently switched out StructreMap for Castle Windsor as the Inversion of Control container on my new project. The main reason for this was to get automatic transactions via Castle’s AutoTx Facility. This means all I have to do in my model is add the TransactionAttribute to any method I need to be transactional. Any sessions injected via the usual Windsor way (Func<ISession> or SessionManager) are automatically flushed and disposed of. It really reduced the amount of boilerplate code that needs to be written. This was a good resource.

Most of my FluentNHibernate installer.

public class FluentNHibernateInstaller : INHibernateInstaller
{
    public FluentConfiguration BuildFluent()
    {
        return Fluently.Configure()
                .Database(SQLiteConfiguration.Standard.UsingFile(filePath))
                .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf(new IbacDataConfiguration())))
                .ExposeConfiguration(o =>
                 {
                     if (databaseType == DatabaseType.SQLLiteFileBased)
                     {
                       if (!File.Exists(filePath))
                           BuildSchema(o);
                       else
                           UpdateSchema(o);
                     }
                     else if(databaseType == DatabaseType.SQLLiteInMemory)
                           BuildSchmea(o);
                     else if(databaseType == DatabaseType.SQLServer2005)
                           UpdateSchema(o);
                 });
    }

    private static void BuildSchmea(Configuration cfg)
    {
        SchemaUpdateLog.InfoFormat("-- Create script, circa {0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        new SchemaExport(cfg).Execute(SchemaUpdateLog.Info, true, false);
    }

    private static void UpdateSchema(Configuration cfg)
    {
        SchemaUpdateLog.InfoFormat("Update script, circa {0}",
                        DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
        new SchemaUpdate(cfg).Execute(SchemaUpdateLog.Info, true);
    }
}

Here’s what I use to bootstrap my Dao.Hibernate project. A bit of a snag? Make sure your AutoTxFacility is registered before anything that might be transactional. Same thing for the Factory Support Facility. It has to come before anything that might be created with a factory.

public static void Bootstrap(IWindsorContainer container)
{
    container.AddFacility<AutoTxFacility>();
    container.AddFacility<FactorySupportFacility>();
    container.Register(Component.For<INHibernateInstaller>().ImplementedBy<FluentNHibernateInstaller>());
    container.AddFacility<NHibernateFacility>(
         o => o.DefaultLifeStyle = DefaultSessionLifeStyleOption.SessionTransient);
     container.Register(Component.For<ISomeDao>().ImplementedBy<SomeDao>());
}

Then in my actual application project:

IoC = new WindsorContainer();
NHibernateDao.Bootstrap(IoC);
IoC.Register(Component.For<ISomeModel>().ImplementedBy<SomeModel>().LifestyleSingleton());

The layers

  1. Project.Domain – contains all my domain objects, no references, that’s it
  2. Project.Dao – Interfaces for the daos
  3. Project.Dao.Hibernate – implemented daos, FluentNHibernateInstaller, bootstrapping code, and generated sessions (per call)
  4. Project.App – Everything else
    1. Models (singletons) – The models with business logic and transactions
    2. ViewModels (one per view) – Mapping to what’s displayed
    3. Views – user controls, windows, etc.

A typical dao implementation:

public class SomeDao : ISomeDao
{
    private static readonly ILog Log = LogManager.GetLogger(
        MethodBase.GetCurrentMethod().DeclaringType);
    private readonly Func<ISession> _session;

    public SomeDao(Func<ISession> session)
    {
        _session = session;
    }

    #region ISomeDao Members

    public virtual IEnumerable<IIbacData> GetAllSomeDomainObject()
    {
        return _session().CreateCriteria<SomeDomainObject>().List<SomeDomainObject>();
    }
...
}

A typical Model:

public class SomeDomainObjectModel : ModelBase, ISomeDomainObjectModel
{
    #region ISomeDomainObjectModel Members

    public virtual IEnumerable<ISomeDomainObject> GetAllData()
    {
        return IoC.Resolve<ISomeDao>().GetAllSomeDomainObject();
    }

    [Transaction]
    public virtual void SaveNew(ISomeDomainObject data)
    {
        IoC.Resolve<ISomeDao>().SaveNew(data);
        RaiseNewData(data);
    }
...
}
Tagged with: , , , , ,
Posted in .Net, Inversion of Control
One comment on “Fluent NHibernate, Castle Windsor, and Automatic Transactions
  1. OutOfTouch's avatar OutOfTouch says:

    You don’t use DTO’s and no repository? Where are your entities and mappings?

Leave a reply to OutOfTouch Cancel reply