NHibernate and the specification pattern

by Ricardo Peres ·
Published September 11, 2014
· Updated November 1, 2017

This is my first guest post at Agile-Code! I wish to thank my friend Zoran Maksimovic (@zoranmax) for the invitation! Hope the blog’s readers like it! 🙂

The Specification pattern is well known to .NET developers and has gained significant momentum with the introduction of LINQ expressions. There are lots of implementations, but, for one reason or the other, I wasn’t really happy with any of them, so I decided to write my own, specifically for working with NHibernate.

Using my implementation of the specification pattern, you can write detached LINQ queries (something that NHibernate does not have at the moment) which can then be applied to NHibernate for obtaining results. As an appetizer, here are some examples:

We build a specification with an arbitrarily complex condition and we can apply paging, ordering and eager fetching to it. This does not come from the Specification pattern, but it is something that NHibernate can use. In the end, we ask NHibernate to retrieve the results for the specification.

Implementation

First, we have an interface definition (well, two), which only differ to other well-known implementations because of the Expression property:

This is a static class with some extension methods and some internal helper ones. It takes care of composing specifications together in a fluent interface (And and Or), reversing the condition (Not), applying paging (Take and Skip), fetching related associations (Fetch) and building initial specifications (All and Where). For the integration with NHibernate, there is also an extension method over ISession, QueryBySpecification.

Conclusion

Some things noteworthy:

The SpecificationExtensions class applies some “magic” to extract the conditions, paging and ordering parts of the expression. It could be done differently, maybe with an ExpressionVisitor implementation; as it is now, it requires some structure in place, so it really only works well with specifications built with the supplied methods;

The IsSatisfiedBy method, of course, does not care about the paging, ordering and fetching, only the condition;

The Expression property – and the ISpecification instance itself – should be immutable, hence the fluent methods return new instances;

Unlike other implementations, I do not have OrCondition, AndCondition, NotCondition and the likes; instead of that, I had to use some slightly complex expression manipulations – see the And, Or and Not methods for some examples;

Yes, it probably could be improved! Smile Feel free to send me your suggestions, I’ll have a look and give credit to whom deserves it!