This is an article which continues on a project that I started in a previous article about how to configure NHibernate using Fluent NHibernate. In this article we’ll use the Fluent NHibernate auto-mapping feature and test it using NUnit.
We’ll also let NHibernate generate the tables for us in our database so that we don’t have to think about it. The structure in our application will look like this:
We’ve added two more entitites since the last project, FinancialRecord and RecordType, in Morkonomy.Core. We’ve also added a mapping test in our test project. The first change we’ll make is in our SessionFactoryBuilder:
public static class SessionFactoryBuilder { public static ISessionFactory BuildSessionFactory() { return Fluently.Configure() .Database(SQLiteConfiguration .Standard .UsingFile("Morkonomy.db") .ShowSql() ) .Mappings(m => m.AutoMappings.Add( AutoMap.AssemblyOf<Entity>() .IgnoreBase<Entity>() ) ) .ExposeConfiguration(c => { new SchemaExport(c) .Create(false, true); }) .BuildSessionFactory(); } } |
Some parts has changed. We’ve added .ShowSql() so that we see the queries generated by NHibernate when we test our automapping. Also, we don’t want a table called Entity as it is our base table so we’ve told NHibernate to ingore it (.IgnoreBase
We add a schema export which will generate the tables in our database based on our entities. This will generate a new database structure everytime we use the SessionFactoryBuilder. If you don’t want to generate a new base every time (it can be annoying when you’re not testing but actually run the program) you can use the .Execute() method instead of the .Create() method and tell it only to make changes and update, not to purge and recreate.
It should be noted that Fluent NHibernate shouldn’t really be used with SQLite as there are some dialectal issues (as I’ve come to understand it). Fluent NHibernates SQLite dialect won’t work well with foreign keys as SQLite originally didn’t support foreign keys. It does now, but the Fluent NHibernate dialect hasn’t been completely updated, but you can choose whatever DB provider you want.
When we’ve changed our configuration we’ve solved the table building parts so that we don’t need to care any more about that. It is time to build, and test, our entities:
/// <summary> /// A base class for all other entity classes /// </summary> public class Entity { public virtual int Id { get; set; } } /// <summary> /// A class to used to describe the type of a record /// </summary> public class RecordType : Entity { /// <summary> /// The name of the record type /// </summary> public virtual string Name { get; set; } /// <summary> /// A description of the type /// </summary> public virtual string Description { get; set; } } |
This generates a RecordType entity with the properties Id, Name and Description. All you need to describe a record. For anyone that’s written C# code this is nothing strange. The only thing is that the properties to map must be virtual so that NHibernate can create proxy classes.
There is also our FinancialRecord class:
/// <summary> /// A class representing debit/credit records /// </summary> public class FinancialRecord : Entity { /// <summary> /// The name of the financial debit/credit record /// </summary> public virtual string Name { get; set; } /// <summary> /// The value of the record /// </summary> public virtual double Value { get; set; } /// <summary> /// How often the record is due, byt month (1 = one month) /// </summary> public virtual int PeriodByMonth { get; set; } /// <summary> /// The kind of record we are dealing with /// </summary> public virtual RecordType RecordType { get; set; } } |
What about the testing then? Well, it’s very simple. Create a class called MappingTest (according to the previous overview screenshot) and add the following code:
[TestFixture] public class MappingTest { private ISession m_Session; [SetUp] public void _Setup() { m_Session = SessionFactoryBuilder.BuildSessionFactory().OpenSession(); } [Test] public void FinancialRecordMappingTest() { RecordType recType = new RecordType() { Name = "two", Description = "Another description!?" }; CustomEqualityComparer comparer = new CustomEqualityComparer(); new PersistenceSpecification<FinancialRecord>(m_Session, comparer) .CheckProperty(p => p.Name, "Foo") .CheckProperty(p => p.PeriodByMonth, 3) .CheckProperty(p => p.Value, 5.99) .CheckReference(p => p.RecordType, recType) .VerifyTheMappings(); } [Test] public void RecordTypeMappingTest() { new PersistenceSpecification<RecordType>(m_Session) .CheckProperty(p => p.Name, "Foo") .CheckProperty(p => p.Description, "Foo description!") .VerifyTheMappings(); } } |
As you can see we are using a class called CustomEqualistyComparer. We use this to tell NHibernate how to interpret the entities at the mapping stage. We don’t want it to compare the entities based on their memory allocation reference but rather on their ID’s, so it looks like this:
public class CustomEqualityComparer : IEqualityComparer { public bool Equals(object x, object y) { if (x == null || y == null) { return false; } Entity xEntity = x as Entity; Entity yEntity = y as Entity; if (xEntity == null || yEntity == null) { return x.Equals(y); } return xEntity.Id == yEntity.Id; } public int GetHashCode(object obj) { Entity e = obj as Entity; if (e != null) return e.Id; else return base.GetHashCode(); } } |
If you run this test you should be able to read the following, hopefully, in the console:
------ Test started: Assembly: Morkonomy.Test.dll ------ NHibernate: INSERT INTO "Entity" DEFAULT VALUES; select last_insert_rowid() NHibernate: INSERT INTO "RecordType" (Name, Description, Entity_id) VALUES (@p0, @p1, @p2);@p0 = 'two', @p1 = 'Another description!?', @p2 = 1 NHibernate: INSERT INTO "Entity" DEFAULT VALUES; select last_insert_rowid() NHibernate: INSERT INTO "FinancialRecord" (Name, PeriodByMonth, Value, RecordType_id, Entity_id) VALUES (@p0, @p1, @p2, @p3, @p4);@p0 = 'Foo', @p1 = 3, @p2 = 5,99, @p3 = 1, @p4 = 2 NHibernate: SELECT financialr0_.Entity_id as Id0_0_, financialr0_.Name as Name1_0_, financialr0_.PeriodByMonth as PeriodBy3_1_0_, financialr0_.Value as Value1_0_, financialr0_.RecordType_id as RecordType5_1_0_ FROM "FinancialRecord" financialr0_ inner join "Entity" financialr0_1_ on financialr0_.Entity_id=financialr0_1_.Id WHERE financialr0_.Entity_id=@p0;@p0 = 2 NHibernate: INSERT INTO "Entity" DEFAULT VALUES; select last_insert_rowid() NHibernate: INSERT INTO "RecordType" (Name, Description, Entity_id) VALUES (@p0, @p1, @p2);@p0 = 'Foo', @p1 = 'Foo description!', @p2 = 1 NHibernate: SELECT recordtype0_.Entity_id as Id3_0_, recordtype0_.Name as Name5_0_, recordtype0_.Description as Descript3_5_0_ FROM "RecordType" recordtype0_ inner join "Entity" recordtype0_1_ on recordtype0_.Entity_id=recordtype0_1_.Id WHERE recordtype0_.Entity_id=@p0;@p0 = 1 2 passed, 0 failed, 0 skipped, took 11,90 seconds (NUnit 2.5.7). |
We’ll, then you are on your way with your first Fluent NHibernate auto mapping and testing!

Pingback: A basic Fluent NHibernate configuration | Maffelu.net