NHibernate – HbmNHibContext & FluentNHibContext

In this post I’m going to share some parts of my architechture that I use when working with NHibernate. I’m using a Dependency Injection framework (e.g. Microsoft Unity) to create my repositories, services etc.

All my repositores that are implemented using NHibernate takes something I call a “NHibContext”. The NHibContext has one main responsibility: “Creating Unit of Works” that are used within my repositories. To create these Unit of works, the NHibContext needs a way to create ISession’s from an ISessionFactory. To begin with, I have created two implementations (see below): HbmNHibContext, FluentNHibContext. But first lets look at the base-class:

NHibContext

/// <summary>
/// A NHibernate-context object which operates on a single-database.
/// Offers functionality for creating UnitOfWorks for use in e.g
/// Repositories that uses NHibernate.
/// To create a custom Context implementation, inherit from this
/// class and ensure that SessionFactory is assigned in cTor.
/// </summary>
public abstract class NHibContext
{
    protected ISessionFactory SessionFactory { get; set; }

    /// <summary>
    /// Creates an new UnitOfWork.
    /// </summary>
    /// <returns></returns>
    public NHibUnitOfWork CreateUnitOfWork()
    {
        return new NHibUnitOfWork(SessionFactory.OpenSession());
    }
}

HbmNHibContext
Is setup using plain old fashioned HBM-files and uses Xml-configuration for the database etc.

FluentNHibContext
Uses, like the HbmNHibContext, Xml-configuration for the database, but instead of Hbm-files, it uses Fluent-NHibernate for defining the mapping.

/// <summary>
/// Uses Xml-configuration for setup-config and for mappings is Hbm-files used.
/// </summary>
public class HbmNHibContext : NHibContext
{
    /// <summary>
    /// Initializes a new instance of the <see cref="HbmNHibContext"/> class.
    /// Since you do not provide an assembly that contains the mappings,
    /// you have to provide these via configuration of mapping-resources.
    /// </summary>
    public HbmNHibContext()
        : this(null)
    {}

    /// <summary>
    /// Initializes a new instance of the <see cref="NHibContext"/> class.
    /// </summary>
    /// <param name="assemblyName">The Name of the Assembly containing the mappings.</param>
    public HbmNHibContext(string assemblyName)
    {
        SessionFactory = CreateSessionFactory(assemblyName);
    }

    /// <summary>
    /// Creates and returns a session factory.
    /// </summary>
    /// <param name="assemblyName">Optional Name of the assembly that contains the mappings.</param>
    /// <returns></returns>
    private ISessionFactory CreateSessionFactory(string assemblyName)
    {
        var cfg = new Configuration();
        cfg = cfg.Configure();

        if (assemblyName.IsNotNullOrEmpty())
            cfg.AddAssembly(assemblyName);

        return cfg.BuildSessionFactory();
    }
}
/// <summary>
/// Uses Xml-configuration for setup-config and for mappings is Fluent-NHibernate used.
/// </summary>
public class FluentNHibContext
    : NHibContext
{
    /// <summary>
    /// Initializes a new instance of the <see cref="FluentNHibContext"/> class.
    /// </summary>
    /// <param name="assemblyWithMappings">The assembly containing the Fluent mappings.</param>
    public FluentNHibContext(Assembly assemblyWithMappings)
    {
        SessionFactory = CreateSessionFactory(assemblyWithMappings);
    }

    /// <summary>
    /// Creates and returns a session factory.
    /// </summary>
    /// <param name="assemblyWithMappings">The assembly containing the Fluent mappings.</param>
    /// <returns></returns>
    private ISessionFactory CreateSessionFactory(Assembly assemblyWithMappings)
    {
        var cfg = new Configuration();
        cfg = cfg.Configure();

        return Fluently.Configure(cfg)
            .Mappings(m =>
                      m.FluentMappings.AddFromAssembly(assemblyWithMappings))
            .BuildSessionFactory();

        //return cfg.BuildSessionFactory();
    }
}

HBM-Mappings
My mappings are located in the assembly that contains the repositories and not in the assembly containing my entities. This since the mappings are for storage and not domain-logic, hence the entities that are mapped is located in a sepparate domain-assembly.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
    xmlns="urn:nhibernate-mapping-2.2"
    namespace="Sds.X.Domain" assembly="Sds.X"
    schema="dbo"
    default-access="property"
    default-lazy="true">
  
  <class name="UserAccount" table="UserAccounts">
    <id name="Id" type="Int32" unsaved-value="null">
      <generator class="identity" />
    </id>
    <property name="Username" type="String" not-null="true" unique-key="true" />
    <property name="Password" type="String" not-null="true" />
    <property name="Email" type="String" not-null="true" unique-key="true" />
  </class>
</hibernate-mapping>

Fluent Mappings
My fluent-mappings are located in the same assembly as the one that contains my HBM-mappings.

[Serializable]
public class UserAccountMapping
    : ClassMap<UserAccount>
{
    public UserAccountMapping()
    {
        Table("UserAccounts");

        Id(p => p.Id).GeneratedBy.Identity().Not.Nullable();

        Map(p => p.Username)
            .Not.Nullable()
            .Unique();
        Map(p => p.Email)
            .Not.Nullable()
            .Unique();
        Map(p => p.Password)
            .Not.Nullable();
    }
}

Repositories
My repositories needs an injected NHibContext (preferably from a dependency injection framework), since the repository want’s to get an Unit of work from the Context. All repositories are defined by an interface that is designed to handle aggregate-root-entities. For simplicity I have defined an base-interface that specifies common operations that should exist through all my repositories, so my specific repository-interfaces inherits from this base-interface. Wy I work with interfaces is for being able to mock my repositories when performing tests. I also want to be able to create repositories that uses other persistence-technologies, like SubSonic, Linq-to-SQL or something else.

public interface IRepository<T> where T : class
{
    ITransaction CreateTransaction();

    void Insert(T item);
    void Update(T item);
    void Delete(T item);

    T SingleBy(Expression<Func<T, bool>> query);

    IList<T> List();
    IList<T> ListBy(Expression<Func<T, bool>> query);
}

For centralizing common functionality amongst my repositories i have created a base-class for my NHibernate-based repositories.

public abstract class NHibRepository<T> : IRepository<T>
    where T : class, new()
{
    protected NHibContext Context { get; private set; }

    protected NHibRepository(NHibContext context)
    {
        Context = context;
    }

    public virtual ITransaction CreateTransaction()
    {
        return new Transaction();
    }

    public virtual void Insert(T item)
    {
        using(var uow = Context.CreateUnitOfWork())
        {
            uow.Insert<T>(item);
            uow.SaveChanges();
        }
    }

    public virtual void Update(T item)
    {
        using (var uow = Context.CreateUnitOfWork())
        {
            uow.Update<T>(item);
            uow.SaveChanges();
        }
    }

    public virtual void Delete(T item)
    {
        using (var uow = Context.CreateUnitOfWork())
        {
            uow.Delete<T>(item);
            uow.SaveChanges();
        }
    }

    public virtual T SingleBy(Expression<Func<T, bool>> query)
    {
        T result;

        using (var uow = Context.CreateUnitOfWork())
        {
            result = uow.GetItemBy<T>(query);
        }

        return result;
    }

    public virtual IList<T> List()
    {
        IList<T> result;

        using (var uow = Context.CreateUnitOfWork())
        {
            result = uow.GetList<T>();
        }

        return result;
    }
    public virtual IList<T> ListBy(Expression<Func<T, bool>> query)
    {
        IList<T> result;

        using (var uow = Context.CreateUnitOfWork())
        {
            result = uow.GetListBy<T>(query);
        }

        return result;
    }
}

Consume the infrastructure (core-lib)
So far we have mostly been dealing with basic infrastructure code that doesn’t change so much. Now lets look at how this is consumed in the “domain”. My repositories for my aggregates than looks like:

public class UserAccountRepository : NHibRepository<UserAccount>, IUserAccountRepository
{
    public UserAccountRepository(NHibContext context)
        : base(context)
    {}
}

Consuming the repository
The code shown below uses a simple factory method. This is just for brevity. Usually I get the instance from an ObjectSpace that uses a dependecy-injection framework to resolve the correct implementation.

[TestMethod]
public void CanInsertSingleUser()
{
    var newUserAccount = CreateUserAccount();

    IUserAccountRepository userRepository = CreateRepository();
    userRepository.Insert(newUserAccount);

    Assert.AreEqual(1, StorageTestHelper.RowCount(UserAccountsTableName));
}

private static IUserAccountRepository CreateRepository()
{
    return new UserAccountRepository(StorageTestHelper.NHibContext);
}

Thats it for now. I hope you have found it interesting.

//Daniel