I haven’t been using it long but I am already a huge fan of Fluent NHibernate. In case you haven’t yet heard about it, Fluent NHibernate allows you to replace those pesky (perfectly functional, but pesky) NHibernate XML mapping files with strong-typed C# code.

As an example, take the following XML mapping file (taken directly from the Fluent NHibernate Wiki):

<?xml version="1.0" encoding="utf-8" ?>  
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"  
  namespace="QuickStart" assembly="QuickStart">  
 
  <class name="Cat" table="Cat">  
    <id name="Id">  
      <generator class="identity" />  
    </id>  
 
    <property name="Name">  
      <column name="Name" length="16" not-null="true" />  
    </property>  
    <property name="Sex" />  
    <many-to-one name="Mate" />  
    <bag name="Kittens">  
      <key column="mother_id" />  
        <one-to-many class="Cat" />  
      </bag>  
  </class>  
</hibernate-mapping>

Compare that to the equivalent in Fluent NHibernate:

public class CatMap : ClassMap<Cat>
{
  public CatMap()
  {
    Id(x => x.Id);
    Map(x => x.Name)
      .Length(16)
      .Not.Nullable();
    Map(x => x.Sex);
    References(x => x.Mate);
    HasMany(x => x.Kittens);
  }
}

Neat huh? And Fluent NHibernate has a lot more to offer, like automatic testing of your mappings. If you haven’t done so yet, go check it out. I’ll wait.

Are you back? Convinced that Fluent NHibernate is the bees knees? Then let me introduce you to another NHibernate project, NHibernate Burrow. NHibernate Burrow is:

a light weight middleware developed to support .Net applications using NHibernate by providing advanced and smart session/transaction management and other facilitates.

What does this mean? In short (and not doing Burrow enough justice by far) it means that Burrow takes care of handling your NHibernate session management in ASP.Net applications. A common approach to session management in ASP.Net is to create a session in the Application_BeginRequest method of Global.asax and to end the session in its EndRequest counterpart. But to get this working properly a lot of ‘what if’s need to be taken care of. Burrow takes all of this out of your hands. It uses a custom HttpModule to literally take care of everything. All you have to do is call GetSession somewhere in your code.

I’ll give you a couple of minutes to go check Burrow out, too. Go on.

If you have played around with Burrow you’ll have noticed that its configuration is extremely simple. There is one caveat though. Burrow wants you to do your configuration in XML files. Wait a minute, you’ll say, didn’t we just get rid of those by using Fluent Nhibernate?

Yes we did. And luckily, with a little work we can tell Burrow to use Fluent NHibernate for our configuration needs. First, we need to make a tiny change to our web.config. The standard Burrow configuration section looks like this:

<NHibernate.Burrow>
  <persistenceUnits>
    <add name="PersistenceUnit1" nh-config-file="~/hibernate.cfg.xml"   />
  </persistenceUnits>
</NHibernate.Burrow>

We’ll need to tell Burrow to use a custom class (that we’ll be creating shortly) to get its configuration.

<NHibernate.Burrow customConfigurator="ReverseAlchemy.FluentBurrow.FluentConfigurator, ReverseAlchemy.FluentBurrow">
</NHibernate.Burrow>

Then, we create a new class to implement to IConfigurator interface:

public class FluentConfigurator : IConfigurator
{
    public void Config(IPersistenceUnitCfg puCfg, Configuration nhCfg)
    {
        Fluently.Configure(nhCfg)
                .Database(/* your database configuration */)))
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<SomeType>()
                                               .Conventions.Add(ForeignKey.EndsWith("Id")))
                .BuildConfiguration();
    }
 
    public void Config(IBurrowConfig val)
    {
        val.PersistenceUnitCfgs.Add(new PersistenceUnitElement { Name = "PersistenceUnit1", 
                                                                 NHConfigFile = null });
    }
}

A few things to note here. The second Config method is called only once and is used to add PersistenceUnits to the Burrow configuration, same as the PersistenceUnits element in the original configuration. The first Config method is called once for each PersistentUnit so that is where the magic takes place.

We pass the nhCfg variable to the Fluently.Configure method. This tells Fluent NHibernate we’ll be using this as a base for our configuration. We then set up our connection string, mappings, conventions and whatnot. Finally we call the BuildConfiguration method, which writes our configuration into the nhCfg variable. Make sure you call this method! Without it, your mappings will not be configured and you’ll spend days trying to figure out what went wrong. Lucky for you I already went through that πŸ˜‰

And this is really all you need to make NHibernate Burrow and Fluent NHibernate play nicely together.

I hope this post was useful to you.

Erik

If you liked this post, please click on one of the advertisements below. Thanks!


6 Responses to “Configuring NHibernate Burrow using Fluent NHibernate”

  1. 1 Jason

    Erik–

    I followed your post on implementing fluent with burrow and am experiencing an issue I’m hoping perhaps you could shed some light on.

    I receive this error:

    Unable to get persistence unit without an entity type when there are more than one session factories.

    This occurs on the line

    new BurrowFramework().GetSession()

    Thoughts..?

  2. 2 Erik Burger

    Hi Jason,

    What this looks like to me is that you might have more than one persistence unit declared but without your code I can do little more than guess. If you’d like to send me your code I’d be more than willing to help you out a bit more. My address is eburger at reversealchemy dot net.

    Cheers,

    Erik

  3. 3 Jay Bohac

    Hey Erik,

    I’m trying to figure out how to map to multiple databases (two), but stuck trying to figure out how to set up the fluent configuration. Any ideas?

    -J

  4. 4 Erik Burger

    Hi Jay,

    I haven’t had any hands-on with that but I did dig up a few articles/posts that might point you in the right direction:

    http://stackoverflow.com/questions/2698503/how-to-identify-a-particular-entitys-session-factory-with-fluent-nhibernate-and
    http://codebetter.com/blogs/karlseguin/archive/2009/03/30/using-nhibernate-with-multiple-databases.aspx
    http://www.codeproject.com/KB/aspnet/NHibernateMultipleDBs.aspx

    Of course that still leaves you with the challenge of getting Fluent and Burrow work nicely with multiple databases. If I’d have to hazard a guess I’d say that setting up multiple persistence units in Burrow should do the trick and then setting up the configuration with Fluent based on which PU you are looking at.

    I’m pretty sure I will be running into the same requirement in my current project pretty soon so if I have more information to share I will definitely do so.

    Good luck and if there’s anything else I can help with or if you need to bounce ideas, let me know.

    Erik

  5. 5 Jay Bohac

    Hey Erik,

    I resolved my issue and it goes like this:

    public void Config(IBurrowConfig val)
    {
    val.PersistenceUnitCfgs.Add(new PersistenceUnitElement
    {
    Name = “P1”,
    NHConfigFile = null
    });
    val.PersistenceUnitCfgs.Add(new PersistenceUnitElement
    {
    Name = “p2”,
    NHConfigFile = null
    });
    }

    And:

    public void Config(IPersistenceUnitCfg puCfg, Configuration nhCfg)
    {
    switch (puCfg.Name)
    {
    case “P1”:
    var FirstOracleConfig = OracleClientConfiguration.Oracle10
    .ConnectionString(c => c.FromConnectionStringWithKey(“FirstDb”));
    Fluently.Configure(nhCfg)
    .Database(FirstOracleConfig)
    .Mappings(m => m.FluentMappings
    .Add()
    .Add())
    .BuildConfiguration();
    break;

    case “P2”:
    var SecondOracleConfig = OracleClientConfiguration.Oracle10
    .ConnectionString(c => c.FromConnectionStringWithKey(“SecondDB”));
    Fluently.Configure(nhCfg)
    .Database(SecondOracleConfig )
    .Mappings(m => m.FluentMappings
    .Add()
    .Add())
    .BuildConfiguration();
    break;
    }
    }

    Hope this helps…

    -Jay

  6. 6 Erik Burger

    Hi Jay,

    Excellent! Thanks for posting your solution, I am sure it’ll come in handy

    Erik

Leave a Reply


*