Creating a common generic and extensible NHiberate Repository

In my previous post Conversation Per Business Transaction using PostSharp and IoC I dealt with the session management aspect of NHiberate however by the end of my development of the business conversation aspect I realized that my current data provider scheme created a lot of duplicate code. As we all know any code that is duplicated becomes a nightmare to maintain so I went through and refactored first a truly generic repository.

public interface IRepository<T>
{
    ICriteria GetAll();
    T Get<U>(U id);
    void Save(T obj);
    ICriteria GetRange(int resultSet, int rangeSize);
}

This is a rather basic interface that will handle the most common operations to my data providers, currently it can handle getting all of the items in my database for a type, a page collection into the list of items in my database, get a specific item and save a new item (or update an existing item). The only minorly unsightly part is the Get<U> method this just allows passing any type of ID instead of declaring it as int statically.

On to implementing the interface:

public class Repository<T> : IRepository<T>
{
    private readonly IConversation _conversation;

    public Repository(IConversation conversation)
    {
        _conversation = conversation;
    }

    #region IRepository<T> Members

    ICriteria IRepository<T>.GetAll()
    {
        return _conversation.Session.CreateCriteria(typeof (T))
            //.SetCacheable(true)
            //.SetCacheMode(CacheMode.Normal)
            ;
    }

    T IRepository<T>.Get<U>(U id)
    {
        return _conversation.Session.Get<T>(id);
    }

    void IRepository<T>.Save(T obj)
    {
        _conversation.Session.SaveOrUpdate(obj);
    }

    ICriteria IRepository<T>.GetRange(int resultSet, int rangeSize)
    {
        return _conversation.Session.CreateCriteria(typeof (T))
            //.SetCacheable(true)
            //.SetCacheMode(CacheMode.Normal)
            .SetFirstResult(resultSet*rangeSize)
            .SetMaxResults(rangeSize - 1)
            ;
    }

    #endregion
}

This class contains rather basic interactions with NHiberate, if you’re not familiar with the CreateCriteria querying method in NHibernate take a look at Chapter 12. Criteria Queries. Other than that I can at an application level enable or disable output caching for my generic repository, currently I’m still working on getting my second level caching implementation working so right now I have it disabled as you can see it’s commented out.

By returning the ICriteria from the repository it allows us to pass on the full power of NHibernate and allow us to create further data provider specific queries.

Next I created an abstract base class for my actual data providers:

public abstract class DataProviderBase<T>
{
    protected readonly IConversation _conversation;
    protected readonly IRepository<T> _repoistory;

    protected DataProviderBase(IConversation conversation)
    {
        _conversation = conversation;
        _repository = new Repository<T>(_conversation);
    }
}

This base class just holds the fields for the business conversation (or ISession) and my newly created generic repository. Now on to my true concrete implementation of my data provider:

public class EmployeeDataProvider : DataProviderBase<Employee>, IEmployeeDataProvider
{
    [InjectionConstructor]
    public EmployeeDataProvider(IConversation conversation) : base(conversation)
    {
    }

    #region IEmployeeDataProvider Members

    IList<Employee> IEmployeeDataProvider.GetAll()
    {
        return _repository.GetAll().List<Employee>();
    }

    IList<Employee> IEmployeeDataProvider.GetRange(int resultSet, int rangeSize)
    {
        return _repository.GetRange(resultSet, rangeSize).List<Employee>();
    }

    Employee IEmployeeDataProvider.Get(int employeeId)
    {
        return _repository.Get(employeeId);
    }

    void IEmployeeDataProvider.Save(Employee employee)
    {
        _repository.Save(employee);
    }

    IList<Territory> IEmployeeDataProvider.GetTerritories()
    {
        return _conversation.Session.CreateCriteria(typeof (Territory)).List<Territory>();
    }

    #endregion
}

In this class we have the delegation of the IRepository (sitting in the abstract base) and we also have direct access to the NHibernate Session so we can add further methods of any kind. This also allows us the flexibility if you’d rather the EmployeeDataProvider had GetEmpoyees() instead of GetAll() it would allow that easily.

Since the repository itself is not exposed at the provider level this allows us to return the actual results in anyway we want. It allows us to further modify the basic queries by adding NHibernate where clauses to the Criteria if we so choose. Since the actual ICriteria won’t be exposed outside of the data provider we don’t need to worry about client interactions causing database usage. This would also allow us if we added NHibernate LINQ to not be concerned with returning the Queryable results for the same reason.

This pattern would also work directly with LINQ2SQL / LINQ2Entities / DLINQ by changing where the NHibernate session is dealt with and using your entity provider. I feel this is a perfect to the data access patern as it protects the code from becoming too unweilding by basing all communication directly through the ICriteria and giving our data providers concrete result lists.

Let me know what you think!

kick it on DotNetKicks.com

Shout it

BloggingContext.ApplicationInstance.CompleteRequest();

Conversation Per Business Transaction using PostSharp and IoC

Earlier this month I encountered the notion of the Conversation per Business transaction paradigm for NHibernate session management as the overrall successor to the session per request pattern. With my exploration on this topic I found it quite confusing to implement in the only existing examples of it. Which is why I wrote a simple version for myself leveraging inversion of control and PostSharp.

Firstly,  everything drives off an IConversation:

public interface IConversation
{
    void Start();
    void Pause();
    void Resume();
    void End();
    void Abort();
    ISession Session { get; }
}

The conversation is a fairly simple idea, just as in a real life conversation you have a start to it, you can pause the conversation (which is how to commit the conversations), resume the conversation, end the conversation and abort the conversation. Imagine the scenario of a school class and students who have learning commited to their memory. A day could follow a similar context as this:

8:00 Class starts
Math is taught, Science is taught
12:00 Class is paused for recess (all information is committed)
13:00 Class is resumed
Creationism is taught, but realized to be made up and Class is aborted
14:00 Class is started again
More subjects are taught
15:00 Class is ended and all information flushed to students long term memory.

This example is fairly contrived but if you replace students with the database and act of class being taught with the conversation it should be pretty clear a flow that could occur over a single session for a conversation.

Next is the actual implementation of the Conversation class.

public class Conversation : IConversation, IDisposable
{
    private readonly INHibernateSessionManager _sessionManager;

    public ISession Session { private set; get; }

    [InjectionConstructor]
    public Conversation(INHibernateSessionManager sessionManager)
    {
        _sessionManager = sessionManager;
    }

    /// <summary>
    /// Starts this instance.
    /// </summary>
    public void Start()
    {
        if (Session != null && (Session.IsOpen || Session.IsConnected))
        {
            Abort();
        }
        Session = _sessionManager.GetSession(FlushMode.Never);
        Resume();
    }

    /// <summary>
    /// Pauses this instance.
    /// </summary>
    public void Pause()
    {
        Commit(Session);

    }

    /// <summary>
    /// Resumes this instance.
    /// </summary>
    public void Resume()
    {
        if (Session == null)
            Start();

        if (Session == null)
            throw new AccessViolationException("Session could not be created");

        if (!Session.IsConnected)
        {
            Session.Reconnect();
        }
        Session.BeginTransaction();
    }

    /// <summary>
    /// Ends this instance.
    /// </summary>
    public void End()
    {
        if (Session == null || !Session.IsOpen) return;

        FlushAndCommit(Session);
        Session.Close();
    }

    /// <summary>
    /// Aborts this instance.
    /// </summary>
    public void Abort()
    {
        if (Session == null || !Session.IsOpen) return;

        if (Session.Transaction != null && Session.Transaction.IsActive)
        {
            Session.Transaction.Rollback();
        }
        Session.Close();
    }

    /// <summary>
    /// Commits the specified session.
    /// </summary>
    /// <param name="session">The session.</param>
    private static void Commit(ISession session)
    {
        if (session.Transaction != null && session.Transaction.IsActive)
        {
            session.Transaction.Commit();
        }
    }

    /// <summary>
    /// Flushes the and commit.
    /// </summary>
    /// <param name="session">The session.</param>
    private static void FlushAndCommit(ISession session)
    {
        if (session.Transaction == null || !session.Transaction.IsActive) return;

        session.Flush();
        session.Transaction.Commit();
    }

    #region Implementation of IDisposable

    public void Dispose()
    {
        End();
    }

    #endregion
}

This class is a little bit long but nothing is that complex and I think every method is very straight forward. I’m going to skip over a few things that are not needed for understanding what this class does. The INHibernateSessionManager is an interface to a class that is a basically a wrapper to NHibernate’s ISessionFactory. For all intensive purposes this class could be ISessionFactory instead and the implementation wouldn’t change other than it would be session = Factory.OpenSession(); session.FlushMode = FlushMode.Never;

The InjectionConstructor attribute is a Microsoft Unity (Inversion of Control framework) specific convention that informs Unity to inject the NHibernate SessionFactory dependency into a Conversation anytime it is created. Unity will store a singleton copy of the SessionFactory for the life of the application.

Next up is the DataProvider class that will actually use the Conversation to talk to the database physically.

public class EmployeeDataProvider : IEmployeeDataProvider
{
    private readonly IConversation _conversation;

    [InjectionConstructor]
    public EmployeeDataProvider(IConversation conversation)
    {
        _conversation = conversation;
    }

    IList<Employee> IEmployeeDataProvider.GetEmployees()
    {
        return _conversation.Session.CreateCriteria(typeof (Employee)).List<Employee>();
    }
}

This is a very basic method that is used with NHiberate, it’s the syntax to get a list of objects from the database. I have some other methods in my provider but the code is less important now onto calling the provider.

[Test]
[BusinessConversation]
public void BusinessConversationTest()
{
    const int id = 9;
    var employee = _provider.GetEmployee(id);
    Assert.IsNotNull(employee);

    var employees = _provider.GetEmployees();
    Assert.IsTrue(employees.Count > 0);

    var territories = _provider.GetTerritories();
    Assert.IsTrue(territories.Count > 0);
}

In the setup call for this test Unity will resolve the _provider and assign it a Conversation which has the SessionFactory in it for opening the session. The same session is used for each of the calls to the database and committed as a single transaction when the method exits. This is done automagically by PostSharp.

PostSharp is an aspect orientated programming framework that allows you to create attributes can trigger methods before entering a method with the attribute and after exiting. The code for the BusinesConversation attribute is

[Serializable]
public sealed class BusinessConversation : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionEventArgs eventArgs)
    {
        var container = HttpContext.Current != null ?
            HttpContext.Current.Application.GetContainer() : UnityTestContainer.Instance;
        var conversation = container.Resolve<IConversation>();
        conversation.Resume();
    }

    public override void OnExit(MethodExecutionEventArgs eventArgs)
    {
        var container = HttpContext.Current != null ?
            HttpContext.Current.Application.GetContainer() : UnityTestContainer.Instance;
        var conversation = container.Resolve<IConversation>();
        conversation.Pause();
    }
}

Now this has some Unity specific code in it where it calls to the container to resolve the Conversation but the important part is that OnEntry to a method with the BusinessConversation attribute the conversation is resumed. This will either resume an existing conversation that’s stored in the session or it will create a new one. When it exits the method the conversation is paused which commits the transaction to the database.

The other code where it does resolution checking on HttpContext or reads from my UntityTestContainer does not really make me happy and eventually will be refactored to be cleaner in one way or another. But this code would be specific to how you interact with your container that would store the Conversations.

The only other issue I have with any of this is exposing the Session from the Conversation, I couldn’t figure out a simplier way for allowing my data providers to actually interact with the session to physically hit the database otherwise. I considered instead of a Conversation containing a session to actually make it implement ISession and assign it to itself during the creation but that didn’t sound right to me even more so.

I’d be grateful for any feedback on my implementation here: good, bad or indifferent. I feel I’ve finally put together a clean simple to understand post on how to correctly manage NHibernate’s session that doesn’t require implementing the UnitOfWork pattern and leverages dependency injection to keep the code seperated and decoupled as much as possible. The full source to my project as always can be found on my Assembla page.

kick it on DotNetKicks.com

Shout it

BloggingContext.ApplicationInstance.CompleteRequest();

Adding Inflector to UnityWeb

Today as I was browsing the Fluent NHibernate discussion boards I was reading the post regarding features that the creators of the S#arp Architecture were interested in seeing.

One of the things that was pointed out was that FH doesn’t include a pluralizer which can make convention mapping problem matic.

Take my current AutoPersistanceModel

var persistenceModel = AutoPersistenceModel.MapEntitiesFromAssemblyOf<Employee>()
.WithConvention(c => c.DefaultLazyLoad = false)
.WithConvention(convention =>   convention.GetTableName = type => type.Name + "s")
.WithConvention(convention => convention.GetPrimaryKeyNameFromType = type => type.Name + "ID")
.WithConvention(convention => convention.GetForeignKeyName = prop => prop.Name + "ID")
.WithConvention(convention=>convention.DefaultCache = cache => cache.AsReadWrite())
.WithConvention(c => c.OneToManyConvention = m =>
                                                 {
                                                     m.Cascade.All();
                                                     m.LazyLoad();
                                                 })
.ForTypesThatDeriveFrom<Category>(autoMap =>
                                      {
                                            autoMap.WithTable("Categories");
                                          autoMap.Map(p => p.Name, "CategoryName");
                                      })
.ForTypesThatDeriveFrom<Territory>(autoMap =>
                                       {
                                             autoMap.WithTable("Territories");
                                           autoMap.Map(p => p.Description, "TerritoryDescription");
                                           autoMap.Map(p => p.Region,
 "RegionID").CustomTypeIs(typeof (Region));
                                       })
;

In more than 1 senario I need to force the autoMap to use the correct spelling of a table name instead of just being able to append S on it. With Inflector I can get a much cleaner map and only to have:

var persistenceModel = AutoPersistenceModel.MapEntitiesFromAssemblyOf<Employee>()
.WithConvention(c => c.DefaultLazyLoad = false)
.WithConvention(convention =>   convention.GetTableName = type => Inflector.Pluralize(type.Name))
.WithConvention(convention => convention.GetPrimaryKeyNameFromType = type => type.Name + "ID")
.WithConvention(convention => convention.GetForeignKeyName = prop => prop.Name + "ID")
.WithConvention(convention=>convention.DefaultCache = cache => cache.AsReadWrite())
.WithConvention(c => c.OneToManyConvention = m =>
                                                 {
                                                     m.Cascade.All();
                                                     m.LazyLoad();
                                                 })
.ForTypesThatDeriveFrom<Category>(autoMap =>
                                      {
                                          autoMap.Map(p => p.Name, "CategoryName");
                                      })
.ForTypesThatDeriveFrom<Territory>(autoMap =>
                                       {
                                           autoMap.Map(p => p.Description, "TerritoryDescription");
                                           autoMap.Map(p => p.Region,
 "RegionID").CustomTypeIs(typeof (Region));
                                       })
;

You can download Inflector and it’s source over at Andrew Peter’s blog Inflector.NET.

On a further note I believe I’ve learned how to remove the need to have the specific mappings for my enum properties, Name property and Description property which will significantly reduce the code noise of the auto mapping which will show up soon in another blog bost.

Happy New Year Everyone

I hope everyone had a happy new year and had good holidays to close out last year. I’m still working on UnityWeb I think I finally am close to grasping the last stumbling block I’ve had with NHibernate the session management of it as I’ve just learned of the conversation per business transaction pattern.

Just something I ran across today that should give everyone a brief chuckle is this snippet of code:

if (param[1].Value.GetType() != Type.GetType("System.DBNull"))

Isn’t that just some of the most beautiful code you’ve ever seen?
/sarcasm

You can definitely file this under the Lexicon of Crap code.

UnityWeb back to the North

I’ve decided using the adventureworks database is more of  a hindrance than anything to UnityWeb, I will be switching back to using the Northwind database. I wanted to use the ADW DB in hopes to tackle some more complex situations since databases rarely seem to be optimal to a developer but the numerous schemas and weird cohesion levels in the ADW DB has just turned me off entirely to it. While I’m not a DBA, but this database is just appalling to me and is just a perfect example of why I hate databases in general, they are completely archaic and need to go the way of the dinosaur.

BloggingContext.ApplicationInstance.CompleteRequest();

UnityWeb Status Update

I’ve been continuing on making progress on my UnityWeb solution. I ended up backtracking for a while as I switched from the Northwind database to the Adventureworks database. I have ran my current solution on both the Adventureworks 2005 and 2008 sample so either of them should work.

I was doing my earnest to avoid having to make any changes to the database but I’ve ran into a slight stumbling block for using Fluent Nhibernates auto persistence model that it’s hard to deal with multiple tables in different schemas so I broke down and added some synonyms to the database to handle this.

For anyone that downloads my code from here on out make sure you run these synonym create statements.
USE AdventureWorks

CREATE SYNONYM [dbo].[synEmployee] FOR [AdventureWorks].[HumanResources].[vEmployee]
CREATE SYNONYM [dbo].[synJobCandidate] FOR [AdventureWorks].[HumanResources].[vJobCandidate]
CREATE SYNONYM [dbo].[synVendor] FOR [AdventureWorks].[Purchasing].[vVendor]
CREATE SYNONYM [dbo].[synCustomer] FOR [AdventureWorks].[Sales].[vIndividualCustomer]
CREATE SYNONYM [dbo].[synSalesPerson] FOR [AdventureWorks].[Sales].[vSalesPerson]
CREATE SYNONYM [dbo].[synOrders] FOR [AdventureWorks].[Sales].[SalesOrderHeader]

BloggingContext.ApplicationInstance.CompleteRequest();

UnityWeb

So my UnityWeb project (Unity for DI/IoC, MVP pattern, Fluent-Nhibernate) is nearing release stages. I posted the initial source copy on Assembla. I still have some work to do before I feel it’s closer to a final version and do my full write up on here about it. It will most likely become a multipart series for how much technology it encompasses. The majority of which I am no proven expert on but I have made efforts to learn as much as I could and went through alot of the growing pains trying to figure it out on my own and various blogs online. I feel my combined release should make the adaption of a UnityWeb type solution for your personal usage (or in your organization) much easier and quicker than rolling it from the ground up alone.

BloggingContext.ApplicationInstance.CompleteRequest();