FluentNHibernate

FluentNhibernate framework provides easy way to define mappings in NHibernate. You don’t need to create complex xml files , instead you can use C# syntax and write the code in the “.cs” file. FluentNH generates cfg from it.

Just to show you how this is simple check this class mapping,

        public GroupModelMap()
        {
            Id(x => x.ID);
            Map(x => x.GroupName).Not.Nullable();

            //One
            References(x => x.GroupType).Not.LazyLoad();

            //Many
            HasMany(x=>x.Users);           
        }

Mapped class looks like this :

    public class GroupModel 
    {
        public virtual int ID { get; private set; }
        public virtual string GroupName { get; set; }

        public virtual GroupTypeModel GroupType { get; set; }
        public virtual IList<ProfileModel> Users { get; set; }

    }

Every property needs to be marked as virtual and every mapped class needs ID property. It’s just simple as that. There are many options you can use. But I wont go into details in this post. If you want to try it just check the site.

In this post ,I want to show you other aspects of FluentNHibernate , that can make your life easier. FluentNH is not only about mappings anymore it provides lots of more functionalities.

In Memory Testing

When testing NHibernate layer , it is a good way to use database stored in memory. Unit tests should be isolated , so by running tests on Database Engine you break this rule.

For InMemory DB  , I  prefer the SqlLite database engine. Its quite good and FluentNH has a good “out of box” support for it. Creating InMemory DB can be a painful experience. You can encounter various problems and one of them is session management. With InMemory DB when session is closed data is deleted from memory and you don’t have access to data. In one of the projects , I have implemented my own mechanism based on the Maciej Aniserowicz samples. It worked fine, but also required a lot of testing and improving.

Fortunately for us Fluent NH provides mechanism for creating the session object leaving you problem of implementing the tests. We just need to provide the SqlLite configuration.

Something like :

_configuration = Fluently.Configure()
                  .Database(() => SQLiteConfiguration.Standard.InMemory().ShowSql())
                  .Mappings(x => x.FluentMappings.AddFromAssembly(typeof(ProfileModel).Assembly))
                  .BuildConfiguration();

 

Then you can create session and use it for tests.

var sessionSource = new SingleConnectionSessionSourceForSQLiteInMemoryTesting(configuration);

ISession session = sessionSource.CreateSession()

Testing Nhibernate Mappings

In unit test world with ORM layers it is good idea to test mappings. Writing your own tests can be a mundane and boring task. FluentNHibernate provides  a way to test it quite simply.

You can use the PersistenceSpecification class

new PersistenceSpecification<ForumModel>(session, new IDEqualityComparer())
       .CheckProperty(c => c.Name, "test")
       .CheckProperty(c => c.Author, "test")
       .CheckList<TopicModel>(c => c.Topics,
                   new List<TopicModel>() 
                        { 
                            new TopicModel(){ Text="test"}
                        }
                   )
        .VerifyTheMappings();

This class performs:

  • create ForumModel instance
  • insert this instance to DB
  • retrieve it
  • and verify if returned data is correct

Besides the session parameter this class can take Comparer class which defines the your own comparison idea .

Look at this example. In one of the projects , I am performing comparison based on the unique ID to check if Reference is correct.

    public class IDEqualityComparer : IEqualityComparer
    {
        new public bool Equals(object x, object y)
        {
            #region Comparer

            if (x == null || y == null)
            {
                return false;
            }
            if (x is IModel &amp;&amp; y is IModel)
            {
                return ((IModel)x).ID == ((IModel)y).ID;
            }

            return x.Equals(y); 
            #endregion
        }

        public int GetHashCode(object obj)
        {
            throw new NotImplementedException();
        }
    }

IModel is used here to shorten the code. It contains only ID property. Every model class implements it.

More info

http://wiki.fluentnhibernate.org/Persistence_specification_testing