NHibernate


This is fairly easy if you know the special sauce for encrypting Asp.Net web.config. You can use the built in functionality of Asp.Net. Go to Start => All Programs => Microsoft Visual Studio 2005/2008 => Visual Studio Tools =>Microsoft Visual Studio 2005/2008 Command Prompt.

Type in the following command (for using IIS):

aspnet_regiis.exe -pe "connectionString" -app "/<my virtual directory>"

You should see ‘Encrypting configuration section…" followed by "Succeeded!"

That is the first half. You then need to execute a second command to prevent, "Failed to decrypt using provider ‘RsaProtectedConfigurationProvider’. Error message from the provider: The RSA key container could not be opened".

aspnet_regiis.exe -pa "NetFrameworkConfigurationKey" "ASPNET"

You should see "Adding ACL for access to the RSA Key container…" followed by "Suceeded!"

Here are the two web sites I used to find this:

How to Encrypt connection string in web.config

Encrypting configuration files using protected configuration

Here is an interesting tidbit on using the lazy and outer-join property in Set mapping. A Set is a collection of unique items and is optimized for reading and writing. When using Set remember to assign a data type of HashSet in your class.

The lazy property is by default is set to true. If your code does a session.Get<T> and uses a foreach loop on the Set NHibernate will generate two select statements. Even if you change the lazy property to false you still get two select statements because NHibernate does not control how the Set is loaded. NHibernate in order to avoid the possibility of a Cartesian product generates the two select statements.

When the lazy property is false the Set is loaded when the .Get<T> is called. When the lazy property is set to true then the collection will only be loaded in the foreach loop.

If you want to load both the entity and the Set is a single SQL statement then you must use the outer-join property set to true. However, this is an expensive operations if you only need the Set loaded for certain situations. It is recommended that you don’t set the outer-join property to true.

What should you do? You should manage this at a higher level and not in the mapping. If you need all of the records in a Set to be loaded with the entity then you would use .SetFetchMode as part of your query. This would look something like this:

var myEntity = session.CreateCriteria<T>().SetFetchMode("U",FetchMode.Join).List();

where <T> is the class and U is the Set within the class.

I have Google’d this and tried to find an answer to this error message for weeks.  I got a Error with controller lot of hits from Google but I couldn’t find the definitive answer to correct the error. I’m using Rhino.Commons as part of the application along with Castle project and NHibernate.

So I started a solution from scratch adding the stack components as I went. I got Castle IoC and MonoRail displaying a simple page. I added the Spark View Engine and still got the home/index.spark page to render. When I added the Rhino.Commons components that is when I got the error. That is when I finally had the ‘aha’ moment. All of the Google hits never gave me any real clue about what the problem was. Here is the definitive solution to the problem.

Once Rhino.Commons along with the IoC class is introduced you need to register the controllers. I never put this rather obvious conclusion in place because I wasn’t thinking it was caused by the Rhino.Commons IoC class. I kept looking at the web.config file and the controllers that were being registered there.

Here is how I registered the controller by placing this in the global.asax.cs file.

IoC.Container.Register(
                AllTypes.Of<IController>().FromAssemblyNamed("your controllers"));

All of my controllers extend SmartDispatcherController.

What directory structure should be used for a web based project? There are no hard, Application Structure fast rules for this. The opinions vary and even my typical website project has changed. This is the latest project directory organization that I am using.

There are three projects: Genealogist, Genealogist.Tests and Genealogist.Web. Genealogist.Web is an Add => New Project => Visual C# => Web => ASP.NET Web Application. Don’t use Add => New Web Site => ASP.NET Web Site. This will not play well with the Global.asax/Global.asax.cs file. The other two are just C# class library projects.

The Genealogist.Web application has a special directory, FrameStack. FrameStack itself has three directories: NHibernate, Spark and Windsor. All three have a class named ConfigurationByConvention. As the name implies each of these classes provide methods for configuring the 3rd party libraries without using .XML files.

The Genealogist project has two directories: DomainModel and Queries. More directories may be added in the future as the project is developed. For now YAGNI indicates that this is the minimum of what is needed.

The DomainModel is based on using DDD principles and the entities, value objects, factories and repositories will be created there. The Queries directory is something I added after reading Udi Dahan’s Employing the Domain Model Pattern in MSDN Magazine. It is a separation of read-only query support from the full CRUD requirements found in the DomainModel.

Web References The 3rd party DLLs I used are from the Castle, NHibernate and Spark View Engine open source projects. I’ll add the Rhino.Commons and Fluent NHibernate when I start developing the Domain Model.

Anyway this is my current web site application structure. It uses Castle Windsor and MonoRail along with the Spark View Engine.

I have played with three different approaches to configuring Rhino.Commons, NHibernate and Windsor container for unit testing. I’ve spiked these three flavors in order to investigate building an infrastructure that is open to extension but closed to modification. I’m still in the process of doing my analysis but I now have 3 approaches to  play with.

My last blog entry showed how to use Rhino.Commons with an in memory SQLite database. The example also used Windsor container and it was my initial proof of concept. There are lots of blogs like this but I still had trouble figuring out how to make this rather easy approach work.

Since then I have been refactoring this approach and making it more closely follow the Open-Closed Principle first coined in 1988 by Bertrand Meyer in his book, Object-Oriented Software Construction. Prentice Hall. ISBN 0136290493. There is a very good article on the ObjectMentor blog about the OCP.

The first refactor I did was move away from using the hibernate.cfg.xml file and do it NHibernate configuration dynamically. I did this by creating a ConventionConfiguration class that uses NHibernate.Cfg.Environment static class properties.

using NHibernate;
using Rhino.Commons;
using Configuration = NHibernate.Cfg.Configuration;
using Environment=NHibernate.Cfg.Environment;

namespace CrawBuck.Commons.NHibernate {
    public class ConventionConfiguration : Configuration {
        private readonly Configuration configuration = new Configuration();

        public Configuration getConfiguration() { return configuration; }

        /// <summary>
        /// This is the wiring up point for NHibernate. This sets up the Environment properties for
        /// SQLite in memory database
        /// </summary>
        public void ConfigureNHiberateForSQLite() {
            IDictionary<string, string> properties = new Dictionary<string, string>();
            properties.Add(Environment.ConnectionProvider, "NHibernate.Connection.DriverConnectionProvider");
            properties.Add(Environment.ConnectionDriver, "NHibernate.Driver.SQLite20Driver");
            properties.Add(Environment.ConnectionString, "Data Source=:memory:;Version=3;New=True;");
            properties.Add(Environment.ShowSql, "true");
            properties.Add(Environment.Dialect, "NHibernate.Dialect.SQLiteDialect");
            properties.Add(Environment.ReleaseConnections, "on_close");
            properties.Add(Environment.ProxyFactoryFactoryClass, "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
            configuration.SetProperties(properties);
        }
    }
}

This class will only do two things right now. It will dynamically configure NHibernate to use SQLite and it will return the NHibernate.Cfg.Configuration variable that holds these properties. For my infrastructure work I will later add a method to dynamically configure MS SQL Server database. Unit testing should be fast but there are times when you actually have to hit a real database. I call real database testing ‘integration database testing’ and don’t have my continuous integration build machine run this type of testing at check in. I do want to do integration database testing but I set the build for this to happen at about 4 hour intervals. Currently I’m using CruiseControl.NET but I’m going to be moving to Hudson.

The next change I made was to move the configuration of the Windsor container to a class of its own, BinsorlessUnitOfWorkApplication. This is an extension of Rhino.Commons.HttpModules.UnitOfWorkApplication.

using System;
using Castle.Facilities.FactorySupport;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using NHibernate;
using NHibernate.Cfg;
using Rhino.Commons;
using Rhino.Commons.HttpModules;
using Environment=System.Environment;

namespace CrawBuck.Commons.HttpModules {
    public class BinsorlessUnitOfWorkApplication : UnitOfWorkApplication {
        protected override IWindsorContainer CreateContainer(string windsorConfig) {
            //ignore windsor config string and create it empty…
            return new RhinoContainer();
        }

        /// <summary>
        /// This wires up the IoC Rhino/Windsor container for the basic facilities and components.
        /// </summary>
        public virtual void InitializeContainer() {
            Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
            IoC.Initialize(new WindsorContainer());
            IoC.Container
                .AddFacility<FactorySupportFacility>("factory.support")
                .AddFacility<RhinoTransactionFacility>("transaction")
                .Register(
                Component.For(typeof(IRepository<>)).ImplementedBy(typeof(NHRepository<>)),
                Component.For<IUnitOfWorkFactory>().ImplementedBy<NHibernateUnitOfWorkFactory>());
        }

        public void RegisterSessionFactory(Configuration configuration) {
            (IoC.Resolve<IUnitOfWorkFactory>() as NHibernateUnitOfWorkFactory).RegisterSessionFactory(configuration, configuration.BuildSessionFactory());
        }

        public ISessionFactory GetUnitOfWorkFactory() {
            return (IoC.Resolve<IUnitOfWorkFactory>() as NHibernateUnitOfWorkFactory).NHibernateSessionFactory;
        }
    }
}

I had to override the CreateContainer method in Rhino.Commons.HttpModules.UnitOfWork class to remove the need for the windsor.boo file. Once these two classes were in place I refactored the code from my last blog.

using System;
using System.Reflection;
using CrawBuck.Commons.HttpModules;
using CrawBuck.Commons.NHibernate;
using CrawBuck.Commons.Tests.Repository.Domain;
using NHibernate.Criterion;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using Rhino.Commons;

namespace CrawBuck.Commons.Tests.Repository {
    [TestFixture]
    public class RhinoCommonsUnitOfWork {
        protected BinsorlessUnitOfWorkApplication unitOfWorkApplication = new BinsorlessUnitOfWorkApplication();
        protected ConventionConfiguration cc = new ConventionConfiguration();

        [SetUp]
        public void SetUp() {
            unitOfWorkApplication.InitializeContainer();
            cc.ConfigureNHiberateForSQLite();
            cc.getConfiguration().AddAssembly(Assembly.GetExecutingAssembly());
            unitOfWorkApplication.RegisterSessionFactory(cc.getConfiguration());
        }

        [Test]
        public void CanStartUnitOfWorkTest() {
            Customer customer = new Customer("Alan", "Buck");
            Guid guid = customer.Id;
            using(IUnitOfWork uow = UnitOfWork.Start()) {
                uow.BeginTransaction();
                new SchemaExport(cc.getConfiguration()).Execute(false, true, false, true, UnitOfWork.CurrentSession.Connection, null);
                Repository<Customer>.Save(customer);
                uow.TransactionalFlush();
                Customer loadCustomer = Repository<Customer>.Load(guid);
                Assert.AreEqual(loadCustomer.FirstName, "Alan");
                Assert.AreEqual(loadCustomer.LastName, "Buck");
                DetachedCriteria criteria = DetachedCriteria.For(typeof(Customer)).Add(Restrictions.Eq("Id", guid));
                Customer repositoryCustomer = Repository<Customer>.FindOne(criteria);
                Assert.AreEqual(repositoryCustomer.FirstName, "Alan");
                Assert.AreEqual(repositoryCustomer.LastName, "Buck");
            }
        }
    }
}

The following tests use either the Customer or Person classes.

using System;

namespace CrawBuck.Commons.Tests.Repository.Domain {
    public class Customer {
        private Guid id = Guid.NewGuid();
        private string firstName;
        private string lastName;

        public Customer() { }

        public Customer(string firstName, string lastName)
        {
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public virtual Guid Id { get { return id; } set { id = value; } }
        public virtual string FirstName { get { return firstName; } set { firstName = value; } }
        public virtual string LastName { get { return lastName; } set { lastName = value; } }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-lazy=‘false’
    assembly=‘CrawBuck.Commons.Tests’
    namespace=‘CrawBuck.Commons.Tests.Repository.Domain’
    xmlns=‘urn:nhibernate-mapping-2.2′>
  <class name=‘Customer’>
    <id name="Id" column="Id">
      <generator class="assigned"/>
    </id>
    <property name="FirstName" />
    <property name="LastName"/>
  </class>
</hibernate-mapping>
using System;

namespace CrawBuck.Commons.Tests.Repository.Domain {
    public class Person {
        private Guid id = Guid.NewGuid();
        private string firstName;
        private string lastName;
        private int age;

        public Person() { }

        public Person(string firstName, string lastName, int age)
        {
            this.firstName = firstName;
            this.lastName = lastName;
            this.age = age;
        }

        public virtual Guid Id { get { return id; } set { id = value; } }
        public virtual string FirstName { get { return firstName; } set { firstName = value; } }
        public virtual string LastName { get { return lastName; } set { lastName = value; } }
        public virtual int Age { get { return age; } set { age = value; } }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-lazy=‘false’
    assembly=‘CrawBuck.Commons.Tests’
    namespace=‘CrawBuck.Commons.Tests.Repository.Domain’
    xmlns=‘urn:nhibernate-mapping-2.2′>
  <class name=‘Person’>
    <id name="Id" column="Id">
      <generator class="assigned"/>
    </id>
    <property name="FirstName" />
    <property name="LastName"/>
    <property name="Age" type="int"/>
  </class>
</hibernate-mapping>

The next refactor was to create a test base class that will allow the configuration of both the Windsor container and NHibernate using SQLite to be used by any unit test class.

using System;
using System.Reflection;
using CrawBuck.Commons.HttpModules;
using CrawBuck.Commons.NHibernate;
using CrawBuck.Commons.Tests.Repository.Domain;
using NHibernate.Criterion;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using Rhino.Commons;

namespace CrawBuck.Commons.Tests.Repository {
    [TestFixture]
    public class RhinoCommonsUnitOfWork {
        protected BinsorlessUnitOfWorkApplication unitOfWorkApplication = new BinsorlessUnitOfWorkApplication();
        protected ConventionConfiguration cc = new ConventionConfiguration();

        [SetUp]
        public void SetUp() {
            unitOfWorkApplication.InitializeContainer();
            cc.ConfigureNHiberateForSQLite();
            cc.getConfiguration().AddAssembly(Assembly.GetExecutingAssembly());
            unitOfWorkApplication.RegisterSessionFactory(cc.getConfiguration());
        }

        [Test]
        public void CanStartUnitOfWorkTest() {
            Customer customer = new Customer("Alan", "Buck");
            Guid guid = customer.Id;
            using(IUnitOfWork uow = UnitOfWork.Start()) {
                uow.BeginTransaction();
                new SchemaExport(cc.getConfiguration()).Execute(false, true, false, true, UnitOfWork.CurrentSession.Connection, null);
                Repository<Customer>.Save(customer);
                uow.TransactionalFlush();
                Customer loadCustomer = Repository<Customer>.Load(guid);
                Assert.AreEqual(loadCustomer.FirstName, "Alan");
                Assert.AreEqual(loadCustomer.LastName, "Buck");
                DetachedCriteria criteria = DetachedCriteria.For(typeof(Customer)).Add(Restrictions.Eq("Id", guid));
                Customer repositoryCustomer = Repository<Customer>.FindOne(criteria);
                Assert.AreEqual(repositoryCustomer.FirstName, "Alan");
                Assert.AreEqual(repositoryCustomer.LastName, "Buck");
            }
        }
    }
}

Here is a unit test class that takes advantage of the RepositoryTestsBase class.

using System;
using CrawBuck.Commons.Tests.ForTesting;
using CrawBuck.Commons.Tests.Repository.Domain;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using Rhino.Commons;

namespace CrawBuck.Commons.Tests.Repository {
    [TestFixture]
    public class RepositoryTest : RepositoryTestsBase {
        private ISession session;
        private Person person;
        private Guid guid;

        [TestFixtureSetUp]
        public void TestFixtureSetUp() {
            OneTimeTestInitialize();
        }

        [SetUp]
        public void SetUp() {
            person = new Person("Alan", "Buck", 62);
            guid = person.Id;
        }

        [Test]
        public void ShouldCreateRepositoryTest() {
            session = CreateSession();
            session.Save(person);
            session.Flush();
            session.Clear();
            Person loadPerson = session.Load<Person>(guid);
            Assert.AreEqual(loadPerson.FirstName, "Alan");
            Assert.AreEqual(loadPerson.LastName, "Buck");
            Assert.AreEqual(loadPerson.Age, 62);
            session.Dispose();
        }

        [Test]
        public void ShouldCreateUsingIRepositoryTest() {
            using (IUnitOfWork uow = UnitOfWork.Start()) {
                new SchemaExport(configuration).Execute(false, true, false, true, UnitOfWork.CurrentSession.Connection, null);
                Repository<Person>.Save(person);
                uow.TransactionalFlush();
                DetachedCriteria criteria = DetachedCriteria.For(typeof(Person)).Add(Restrictions.Eq("Id", guid));
                Person loadPerson = Repository<Person>.FindOne(criteria);
                Assert.AreEqual(loadPerson.FirstName, "Alan");
                Assert.AreEqual(loadPerson.LastName, "Buck");
                Assert.AreEqual(loadPerson.Age, 62);
            }
        }

        [TearDown]
        public void TearDown() {}
    }
}

That covers two of the approaches to using Rhino.Commons, NHibernate and the Windsor container. The last approach is to use FluentNHibernate. I’m not using the ClassMap of FluentNHibernate. This still uses the .hbm.xml files.

using System;
using System.IO;
using System.Reflection;
using Castle.Windsor;
using CrawBuck.Commons.HttpModules;
using CrawBuck.Commons.NHibernate;
using CrawBuck.Commons.Tests.Repository.Domain;
using FluentNHibernate.AutoMap;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using Rhino.Commons;
using Configuration = NHibernate.Cfg.Configuration;
using Environment=NHibernate.Cfg.Environment;

namespace CrawBuck.Commons.Tests.Repository {
    [TestFixture]
    public class FluentNHibernate {
        private readonly BinsorlessUnitOfWorkApplication unitOfWorkApplication = new BinsorlessUnitOfWorkApplication();
        private Configuration config;
        private readonly ConventionConfiguration cc = new ConventionConfiguration();

        [SetUp]
        public void SetUp() {
            unitOfWorkApplication.InitializeContainer();
            cc.ConfigureNHiberateForSQLite();
            config = cc.getConfiguration();
            config.AddAssembly(Assembly.GetExecutingAssembly());
            CreateRhinoSessionFactoryForSQLite();
        }

        [Test]
        public void CanStartUnitOfWorkTest() {
            Customer customer = new Customer("Alan", "Buck");
            Guid guid = customer.Id;
            using (IUnitOfWork uow = UnitOfWork.Start()) {
                uow.BeginTransaction();
                new SchemaExport(config).Execute(false, true, false, true, UnitOfWork.CurrentSession.Connection, null);
                Repository<Customer>.Save(customer);
                uow.TransactionalFlush();
                Customer loadCustomer = Repository<Customer>.Load(guid);
                Assert.AreEqual(loadCustomer.FirstName, "Alan");
                Assert.AreEqual(loadCustomer.LastName, "Buck");
                DetachedCriteria criteria = DetachedCriteria.For(typeof(Customer)).Add(Restrictions.Eq("Id", guid));
                Customer repositoryCustomer = Repository<Customer>.FindOne(criteria);
                Assert.AreEqual(repositoryCustomer.FirstName, "Alan");
                Assert.AreEqual(repositoryCustomer.LastName, "Buck");
            }
        }

        private void CreateRhinoSessionFactoryForSQLite() {
            IPersistenceConfigurer configurer = SQLiteConfiguration.Standard.InMemory().ShowSql();
            ISessionFactory sessionFactory = Fluently.Configure(config).Database(configurer).Mappings(m => m.FluentMappings.AddFromAssemblyOf<Customer>()).BuildSessionFactory();
            (Rhino.Commons.IoC.Resolve<IUnitOfWorkFactory>() as NHibernateUnitOfWorkFactory).RegisterSessionFactory(config, sessionFactory);
        }
    }
}

You will notice that I have a CreateRhinoSessionFactoryForSQLite method in this test class. It’s there because I’m lazy and it’s late. Maybe in a future blog I will refactor this unit test to use ClassMap and move the CreateRhinoSessionFactoryForSQLite to the BinsorlessUnitOfWorkApplication class. I’m still moving up the learning curve on FluentNHibernate and have only the basic understanding of what all this OSS project has to offer.

There are many examples of writing unit test for NHibernate on the internet. Most of them show how to do this using session factory, session and MS SQL Server. I wanted to do this using Rhino.Commons and SQLite. Here is the code.

using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
using System.Reflection;
using Castle.Windsor;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using Rhino.Commons;
using Rhino.Mocks;

namespace CrawBuck.Commons.Tests.Repository {
    [TestFixture]
    public class RhinoCommonsUnitOfWork {
        protected Configuration configuration;

        [SetUp]
        public void SetUp() {
            System.Environment.CurrentDirectory = AppDomain.CurrentDomain.BaseDirectory;
            WindsorContainer container = new WindsorContainer(Path.GetFullPath(@”RepositoryWindsor.cfg.xml”));
            configuration = new Configuration();
            configuration.Configure();
            Rhino.Commons.IoC.Initialize(container);
        }

        [Test]
        public void CanStartUnitOfWorkTest() {
            Customer customer = new Customer(“Alan”, “Buck”);
            Guid guid = customer.Id;
            using(IUnitOfWork uow = UnitOfWork.Start()) {
                uow.BeginTransaction();
                new SchemaExport(configuration).Execute(false, true, false, true, UnitOfWork.CurrentSession.Connection, null);
                Repository<Customer>.Save(customer);
                uow.TransactionalFlush();
                Customer loadCustomer = Repository<Customer>.Load(guid);
                Assert.AreEqual(loadCustomer.FirstName, “Alan”);
                Assert.AreEqual(loadCustomer.LastName, “Buck”);
                DetachedCriteria criteria = DetachedCriteria.For(typeof(Customer)).Add(Restrictions.Eq(“Id”, guid));
                Customer repositoryCustomer = Repository<Customer>.FindOne(criteria);
                Assert.AreEqual(repositoryCustomer.FirstName, “Alan”);
                Assert.AreEqual(repositoryCustomer.LastName, “Buck”);
            }
        }
    }

    public class Customer {
        private Guid id = Guid.NewGuid();
        private string firstName;
        private string lastName;

        public Customer() { }

        public Customer(string firstName, string lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
        public virtual Guid Id { get { return id; } set { id = value; } }
        public virtual string FirstName { get { return firstName; } set { firstName = value; } }
        public virtual string LastName { get { return lastName; } set { lastName = value; } }
    }
}

I’ve included the using statements because I find that without them you’re never sure what DLLs you need. This was not easy for me to figure out but once I got it to work it was very simple. In the SetUp I create a Windsor container, set up my NHibernate.Cfg.Configuration variable and initialize the Rhino.Commons.IoC with the WindsorContainer. This is most of the configuration that I need. In the CanStartUnitOfWorkTest I create a Customer object and then use it inside of Rhino.Commons.UnitOfWork. The last piece of configuration that I do is to use SchemaExport to create an in memory database with SQLite with the UnitOfWork context. As the code shows I save the Customer object using Rhino.Commons.Repository<Customer>.Save. I retrieve it back out of the database using Rhino.Commons.Repository<Customer>.Load and Rhino.Commons.Repository<Customer>.FindOne.

I use the Windsor.cfg.xml file to configure the container.

<?xml version=“1.0″ encoding=“utf-8″ ?>
<configuration>
  <components>
    <component id=“nhibernate.repository”
                   service =“Rhino.Commons.IRepository`1, Rhino.Commons.NHibernate”
                   type=“Rhino.Commons.NHRepository`1, Rhino.Commons.NHibernate”/>
    <component id=“nhibernate.unit-of-work.factory”
                   service =“Rhino.Commons.IUnitOfWorkFactory, Rhino.Commons.NHibernate”
                    type=“Rhino.Commons.NHibernateUnitOfWorkFactory, Rhino.Commons.NHibernate”/>
  </components>
</configuration>

I use the hibernate.cfg.xml file to configure NHibernate.

<?xml version=“1.0″ encoding=“utf-8″ ?>
<hibernate-configuration  xmlns=“urn:nhibernate-configuration-2.2″ >
  <session-factory>
    <!– properties –>
    <property name=“connection.provider”>NHibernate.Connection.DriverConnectionProvider</property>
    <property name=“connection.driver_class”>NHibernate.Driver.SQLite20Driver</property>
    <property name=“connection.connection_string”>Data Source=:memory:;Version=3;New=True;</property>
    <property name=“show_sql”>true</property>
    <property name=“dialect”>NHibernate.Dialect.SQLiteDialect</property>
    <property name=“proxyfactory.factory_class”>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
    <property name=“connection.release_mode”>on_close</property>

    <mapping assembly=“CrawBuck.Commons.Tests” />
  </session-factory>
</hibernate-configuration>

That is all there is to do this.

I really don’t like using web.config to any .xml file to configure NHibernate. So I choose to dynamically configure NHibernate and here is how I did it.

private void InitSessionFactory() {
cfg = new Configuration();
cfg.Properties[Environment.ConnectionProvider] = “NHibernate.Connection.DriverConnectionProvider”;
string connectionString = (new ConnectionInfoBuilder()).ConnectionString;
cfg.Properties[Environment.ConnectionString] = connectionString;
cfg.Properties[Environment.ConnectionDriver] = “NHibernate.Driver.SqlClientDriver”;
cfg.Properties[Environment.Dialect] = getSqlDialect(connectionString);
sessionFactory = cfg.BuildSessionFactory();
}

private string getSqlDialect(string connectionString) {
string sqlDialect = String.Empty;
bool is2005 = false;
IDbConnection conn = null;

try {
conn = new SqlConnection(connectionString);
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = “SELECT @@VERSION”;
cmd.CommandType = CommandType.Text;
conn.Open();
IDataReader dr = cmd.ExecuteReader();
if (dr.Read()) {
string results = (string) dr.GetValue(0);
is2005 = results.Contains(”Microsoft SQL Server 2005″);
}
dr.Close();
} catch (SqlException sqle) {
} finally {
if(conn != null) {
conn.Close();
}
}

return is2005 ? “NHibernate.Dialect.MsSql2005Dialect” : “NHibernate.Dialect.MsSql2000Dialect”;
}

During the instantiation of the NHibernate class a call is made to InitialSessionFactory. Inside this method all of the necessary configuration requirements are set up. Because you may have to support both MS SQL Server 2000 or 2005 (and next year 2008) a call to getSqlDialect is made to determine which MS SQL Server I am dealing with. Because I haven’t got NHibernate configured yet I use plain old SqlClient classes to get the information directly from SQL Server.

Over the last month or six weeks I have gotten much to do at work and little time to spend on blogging. I just passed through a period of trying to use an immature company-grown framework to deliver my task. This turned out to be unsuccessful. In time it will be successful but right now it is not ready for prime time deployment. So I had to devote many hours to learning how to use the framework and found many problems that had to be communicated to the framework developers.

It finally became apparent that I wasn’t going to be able to deliver on this framework within the time allotted. So I have how switched gears and will be delivering on what a few of us are calling a federated component model. This could best be described as a loosely coupled way of delivering UI from the database that uses MVP design pattern with NHibernate and a Service facade on a domain driven design model. The best solution would be to use IoC but that is too much to handle in the time frame I have to deliver. The hope is that this will evolve over time and get to where it should be.

One the ways this is loosely coupled is that the domain layer isn’t referencing NHibernate. Instead it is referencing a data access class that manages all of the NHibernate stuff.

If you are familiar with NHibernate then you know that you need to create a session to make the magic happen. I’m intentionally ignoring the mapping here. There are many ways of doing this but the one I’m using is to manage this via the Singleton pattern. Jean Paul Boodhoo has examples of how to code this.

One of the problems I have had is how to get references to NHibernate out of my domain model. This is how I do it. I am only going to show how to code up a GetAll method that would return an IList of generic types. First I need to create an interface.

public interface IRepository<T, IdT> {

IList<T> GetAll();

}

This interface lives inside the data access assembly and will be used by the domain model. The next piece is to create an abstract class that does the actual retrieval of the generic type. This too lives inside the data access assembly.

public abstract class AbstractNHibernateRepository<T, IdT> : IRepository<T, IdT> {

private Type persistentType = typeof (T);

public IList<T> GetAll() {

ICriteria criteria = NHibernateSession.CreateCriteria(persistentType);

return criteria.List<T>() as List<T>;

}

private ISession NHibernateSession {

get { return DBRepository.Instance.GetSession(); }

}

}

I’m obviously not showing the DBRepository class but it holds all of the NHibernate functionality and there are many examples of how to code something like this. The points of interest are the IRepository interface and the AbstractNHibernateRepository class. This is where I will extend IRepository in my domain model and get the retrieval wired up.

In my domain model I will create a class to do this.

public class MyDomainRepositoryFactory {

static MyDomainRepositoryFactory() {

DBRepository.Instance.AddAssembly(”MyDomain”);

}

public IMyDORepository GetMyDORepository() {

return new MyDORepository();

}

public class MyDORepository : AbstractNHibernateRepository<MyDO, int>, IMyDORepository {}

public interface IMyDORepository : IRepository<MyDO, int> {}

}

This class is instantiated using the MonoState pattern. I like this better than the Singleton because it avoids any timing issues that can rarely occur with the Singleton pattern. I will show the .AddAssembly method. I have dynamically created the NHibernate configuration in DBRepository and have a private Configuration property along with a private ISessionFactory property .

public void AddAssembly(string assembly) {

cfg.AddAssembley(assembly);

sessionFactory = cfg.BuildSessionFactory();

}

So I’m dynamically adding the assembly the first time I instantiate the domain repository and calling the .BuildSessionFactory again to get all the mapping and domain objects wired up.

Where I would like to finally go is to use IoC and totally eliminate the need for this but right now I’m using a pseudo dependency injection of my domain repository. This gets me the loose coupling and removes any references to NHibernate from my domain classes.

There is not a lot of good examples for NHibernate mapping. I struggle to figure this stuff out but once I get it it always seems so simple.

In the AdventureWorks Person schema there is a foreign key reference from the StateProvince table to the CountryRegion table by the CountryRegionCode column. Here is the StateProvince class code:

namespace AWSandbox.Domain.Person {
public class StateProvince {
private int id;
private string stateProvinceCode;
private CountryRegion countryRegion;
private bool isOnlyStateProvinceFlag;
private string name;
private int territoryId;

public int Id {
get { return id; }
set { id = value; }
}

public string StateProvinceCode {
get { return stateProvinceCode; }
set { stateProvinceCode = value; }
}

public CountryRegion CountryRegion {
get { return countryRegion; }
set { countryRegion = value; }
}

public bool IsOnlyStateProvinceFlag {
get { return isOnlyStateProvinceFlag; }
set { isOnlyStateProvinceFlag = value; }
}

public string Name {
get { return name; }
set { name = value; }
}

public int TerritoryId {
get { return territoryId; }
set { territoryId = value; }
}
public string CountryRegionName {
get { return CountryRegion.Name; }
}
}
}

Notice that the CountryRegionName only has a getter and that it really is using the CountryRegion class to return the Name property.

Here is the mapping:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<hibernate-mapping xmlns=”urn:nhibernate-mapping-2.2″ assembly=”AWSandbox.Domain” namespace=”AWSandbox.Domain”>
<class name=”AWSandbox.Domain.Person.StateProvince, AWSandbox.Domain” table=”Person.StateProvince” lazy=”false”>
<id name=”Id” column=”StateProvinceID”>
<generator class=”native”/>
</id>
<property name=”StateProvinceCode” column=”StateProvinceCode” type=”string” />
<property name=”IsOnlyStateProvinceFlag” column=”IsOnlyStateProvinceFlag” type=”Boolean” />
<property name=”Name” column=”Name” type=”string” />
<many-to-one name=”CountryRegion”class=”AWSandbox.Domain.Person.CountryRegion”
column=”CountryRegionCode” cascade=”all” />
</class>
</hibernate-mapping>

I’m using the <many-to-one> mapping to include the CountryRegion data with the StateProvince data. Now this is how you would display the data in a GridView:

<asp:GridView ID=”StateProvinceGridView” AutoGenerateColumns=”false” runat=”server”>
<Columns>
<asp:BoundField DataField=”Id” HeaderText=”ID”/>
<asp:BoundField DataField=”StateProvinceCode” HeaderText=”Code” />
<asp:BoundField DataField=”IsOnlyStateProvinceFlag” HeaderText=”Flag” />
<asp:BoundField DataField=”Name” HeaderText=”Name” />
<asp:BoundField DataField=”CountryRegionName” HeaderText=”Country Region” />
</Columns>
</asp:GridView>

I’m assigning an IList<StateProvince> objects to the GridView.DataSource and calling GridView.DataBind() to populate the grid. I’m also using the MVP (model view presenter) design pattern to move the data out of the database, through my domain, presentation and service layers and arriving in tabular format on the web page.

This is not original thinking on my part but only gleaned from Jimmy Nilsson’s “Applying Domain-Driven Design and Patterns” book.

Applying Domain-Driven Design

He does an excellent job pointing out the limitations that you may encounter when deciding to use NHibernate. Our team has decided and will shortly deliver a new feature to the application suite that uses NHibernate. So as we commit further down this path I want to preserve and share this.

At a previous company our team was using the database to manage the workflow and not using Domain-Driven Design. The choice was made to move the processing out of the middle tier and let the power of the database handle the state changes with logic in the stored procedures. If you need to leverage the database’s performance and processing capabilities then it is more difficult with O/R Mapping.

Any set-based processing will be by the row because of the O/R Mapping where SQL would do it as global column change on the table.

It is possible to create so much database work in the domain that O/R Mapping is not capable of processing it efficiently.

If you need to update a column based on a selection criteria then O/R Mapping requires you to read the row, make the column change and persist the row back to the database rather than issuing a SQL update statement.

In some situations you may only need a few pieces of data from the database but O/R Mapping will force you into reading all of the data. This becomes huge as more complex relationships are defined in the domain model. Lazy Load coupled with Aggregate design can help to reduce this problem but it is something that needs to be carefully thought out.

Another issue comes from Lazy Load where you select a collection of parent entities and move through each one selecting child entities associated with them. It is actually more efficient to not use Lazy Load.

These are limitations you are bound by when you use O/R Mapping. However, NHibernate has a unique limitation and that is Identity Field. NHibernate will obtain these values through insertion early and it may be sooner than is needed.