NHibernate – Custom Id-generator

Recently I had a case where I needed to switch from the Identity generator to the HiLo generator in an existing project with existing data. Why? Well for one thing it gives better performance since identities brakes the ability to use batch inserts, since the generated Id needs to be returned (selected) after each insert.

I didn’t want to go through and configure params for each entity, hence I created a custom implementation of an Id-generator and added some conventionbased configuration in that class instead.

How to setup HiLo the normal way

The xml below is taken from 5.1.4.2 – Hi/Lo Algorithm – (http://www.nhforge.org/doc/nh/en/index.html#mapping-declaration-id) You can of course skip the params and go with default values.

<id name="Id">
	<generator class="hilo">
			<param name="table">hi_value</param>
			<param name="column">next_value</param>
			<param name="max_lo">100</param>
	</generator>
</id>

This will let every entity share the same table (that’s ok) and the same column for the next hi-value. For me, this wasn’t something I wanted. I wanted one specific value per entity. I also wanted one row per entity so that I could keep away from unnecessary update locks.

I wanted the following table:

create table dbo.NHibHiLoIdentities
(
	EntityName varchar(128) not null primary key,
	NextHiValue bigint not null
)

Custom generator

To get the behavior I wanted I extended the existing TableHiLoGenerator.

public class NHibIdGenerator : TableHiLoGenerator
{
    public override void Configure(IType type, IDictionary<string, string> parms, Dialect dialect)
    {
        if (!parms.ContainsKey("table"))
            parms.Add("table", "NHibHiLoIdentities");

        if (!parms.ContainsKey("column"))
            parms.Add("column", "NextHiValue");

        if (!parms.ContainsKey("max_lo"))
            parms.Add("max_lo", "100");

        if (!parms.ContainsKey("where"))
            parms.Add("where", string.Format("EntityName='{0}'", parms["target_table"]));

        base.Configure(type, parms, dialect);
    }
}

This way, if I want, I can specify the params in the xml-mapping, but if I don’t they will be injected in the Configure override. The trick is the where criteria. This tells NHibernate that I want to have a where criteria against the column “EntityName” generated when the next Hi-value is going to be checked out. I use the name of the entity which is allready populated in the dictionary.

Determine the new value

Since there allready was data in the tables for each entity I just looked at the existing Max(Id) for each and inserted a row in the NHibHiLoIdentities with concerns taken to the value of max_lo above.

insert into dbo.NHibHiLoIdentities (EntityName, NextHiValue) values
(
	'Customer',
	coalesce((select max(Id)/100 from dbo.Customer) + 1, 1)
)

Update your mappings

You will also have to update the mappings with information to make use of your Id-generator. It’s not hard. Just specifiy the fullname of your class for the generator element.

<id name="Id">
  <generator class="NHibAdventures.Storage.NHibIdGenerator, NHibAdventures.Storage" />
</id>

That’s it. Happy tweaking.

//Daniel

Ps! If you need a easy get going sandbox environment, checkout https://github.com/danielwertheim/NHibernate-Adventures

NHibernate adventures

Just pushed a new public repository to Github with a simple sandbox environment for testing things out with NHibernate.

It makes use of an IoC-container to manage the lifecycle of SessionFactory, Sessions and has a simple UnitOfWork implementation.

No GUI, just integrationtests so it’s really simple for you to test things out.

https://github.com/danielwertheim/NHibernate-Adventures

//Daniel

NHibernate – Repository pattern

I know that there allready are implementations for NHibernate-based repositories (eg. RhinoTools) but I can’t help to fiddling a bit with a design that I feel comfortable with. When building business applications I like to use a domain model (Read more – Martin Fowler) and to use repositories (Read more – Martin Fowler) for storing my domain objects. When designing we storage-layer (data-access-layer) I always define each repository using an Interface. This is something I do to be able to create fakes and mocks of my repositories; as well as create different implementations of them, e.g. one using NHibernate and another using SubSonic etc. Each implementation has it’s base-classes etc. just to get rid of repetitive boilerplate coding. For my NHibernate base implementation it looks something like this:

NHibContext (see earlier post) is responsible for creating NHibSessions (which is a wrapper around an NHibernate.ISession). The NHibContext is injected in my NHibRepository so that it can create a NHibSession for use within the repository (this is probably something that might get changed and instead a NHibSession will be injected directly). Than I create e.g. a NHibUserAccountRepository that extends the NHibRepository and also implements the IUserAccountRepository. Lets pick it apart.

Why IRepository?
I want a common repository interface independent of which underlying storage framework is used or what domain object I’m dealing with.

public interface IRepository<T> where T : class, IEntity
{
    void Commit();
    void Rollback();

    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);
}

Why IUserAccountRepository?
As I said before, I want to be able to create fakes and mocks of my repositories and I want to be able to use polymorphism when dealing with my domain-object-specific repositories, so that I can work against an interface, independent of the actual implementation.

public interface IUserAccountRepository : IRepository<UserAccount>
{
}

Why NHibRepository
I want a strongly typed repository-base that keeps me from writing boilerplate code in all my specific NHibernate-based repositories.

public abstract class NHibRepository<T> : IRepository<T>, IDisposable
    where T : class, IEntity
{
    protected NHibContext Context { get; private set; }
    protected NHibSession Session { get; private set; }

    protected NHibRepository(NHibContext context)
    {
        Context = context;
        Session = Context.CreateNewSession();
    }

    public void Dispose()
    {
        Disposer.TryDispose(Session);
    }

    public void Commit()
    {
        Session.Commit();
    }

    public void Rollback()
    {
        Session.Rollback();
    }

    public virtual void Insert(T item)
    {
        Session.Insert<T>(item);
    }

    public virtual void Update(T item)
    {
        Session.Update<T>(item);
    }

    public virtual void Delete(T item)
    {
        Session.Delete<T>(item);
    }

    public virtual T SingleBy(Expression<Func<T, bool>> query)
    {
        return Session.GetItemBy<T>(query);
    }

    public virtual IList<T> List()
    {
        return Session.GetList<T>();
    }

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

UserAccountRepository against NHibernate

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

Why NHibSession?
Simple. I want a slimmer and unified interface for interacting with the NHibernate-core and I want it to take care of transactions.

public class NHibSession
    : IDisposable
{
    private ISession InnerSession { get; set; }
    private ITransaction Transaction { get; set; }

    /// <summary>
    /// Initializes a new instance of the <see cref="NHibSession"/> class.
    /// </summary>
    /// <param name="session">The session.</param>
    public NHibSession(ISession session)
    {
        InnerSession = session;
        InnerSession.FlushMode = FlushMode.Commit;
        SetupNewTransaction();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (Transaction != null)
            {
                Transaction.Rollback();
                Transaction.Dispose();
                Transaction = null;
            }

            if (InnerSession != null)
            {
                InnerSession.Dispose(); //InnerSession.Close(); Do not use! It breaks when outer transactionscopes are active! Should only use Dispose.
                InnerSession = null;
            }                
        }
    }

    ~NHibSession()
    {
        Dispose(false);
    }

    public void Commit()
    {
        Transaction.Commit();
        SetupNewTransaction();
    }

    public void Rollback()
    {
        Transaction.Rollback();
        SetupNewTransaction();
    }

    private void SetupNewTransaction()
    {
        if (Transaction != null)
            Transaction.Dispose();

        Transaction = InnerSession.BeginTransaction();
    }

    /// <summary>
    /// Creates and returns a Query.
    /// </summary>
    /// <param name="queryString">The query string.</param>
    /// <returns></returns>
    public IQuery CreateQuery(string queryString)
    {
        return InnerSession.CreateQuery(queryString);
    }

    /// <summary>
    /// Creates and returns a Criteria.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public ICriteria CreateCriteria<T>()
        where T : class
    {
        return InnerSession.CreateCriteria<T>();
    }

    /// <summary>
    /// Gets an item that matches sent expression.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="query">The query.</param>
    /// <returns></returns>
    public T GetItemBy<T>(Expression<Func<T, bool>> query)
    {
        return InnerSession.Linq<T>().SingleOrDefault(query);
    }

    /// <summary>
    /// Returns item via Id.
    /// </summary>
    /// <typeparam name="TReturn"></typeparam>
    /// <typeparam name="TId"></typeparam>
    /// <param name="id"></param>
    /// <returns></returns>
    public TReturn GetItemById<TReturn, TId>(TId id)
    {
        return InnerSession.Get<TReturn>(id);
    }

    /// <summary>
    /// Returns item via NHibernate Criterions.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="criterions"></param>
    /// <returns></returns>
    public T GetItemByCriterions<T>(params ICriterion[] criterions)
    {
        return AddCriterions(InnerSession.CreateCriteria(typeof(T)), criterions).UniqueResult<T>();
    }

    /// <summary>
    /// Returns a list of ALL items.
    /// </summary>
    /// <remarks>ALL items are returned.</remarks>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public IList<T> GetList<T>()
    {
        return GetListByCriterions<T>(null);
    }

    /// <summary>
    /// Returns a list of items matching sent expression.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="query">The query.</param>
    /// <returns></returns>
    public IList<T> GetListBy<T>(Expression<Func<T, bool>> query = null)
    {
        return InnerSession.Linq<T>().Where(query).ToList();
    }

    /// <summary>
    /// Returns list of item matching sent criterions.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="criterions"></param>
    /// <returns></returns>
    public IList<T> GetListByCriterions<T>(params ICriterion[] criterions)
    {
        ICriteria criteria = AddCriterions(InnerSession.CreateCriteria(typeof(T)), criterions);
        IList<T> result = criteria.List<T>();

        return result ?? new List<T>(0);
    }

    /// <summary>
    /// Deletes sent item.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    public void Delete<T>(T obj)
    {
        InnerSession.Delete(obj);
    }

    /// <summary>
    /// Deletes sent item by id.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="TId"></typeparam>
    /// <param name="id"></param>
    public void DeleteById<T, TId>(TId id)
    {
        Delete(GetItemById<T, TId>(id));
    }

    /// <summary>
    /// Deletes by query.
    /// </summary>
    /// <param name="query"></param>
    public void DeleteByQuery(string query)
    {
        InnerSession.Delete(query);
    }

    /// <summary>
    /// Inserts sent item.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    public void Insert<T>(T obj)
    {
        InnerSession.Save(obj);
    }

    /// <summary>
    /// Updates sent item.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    public void Update<T>(T obj)
    {
        InnerSession.Update(obj);
    }

    private static ICriteria AddCriterions(ICriteria criteria, ICriterion[] criterions)
    {
        if (criterions != null)
            for (int c = 0; c < criterions.Length; c++)
                criteria = criteria.Add(criterions[c]);

        return criteria;
    }
}

Consume it
To show you how I consume it, let me show you a simple test.

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

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

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

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

Thats it. Hope you find it inspiring.

//Daniel

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