colinramsay.co.uk

Finders with DetachedCriteria

17 Dec 2007

I should file this under "things that are probably a design pattern but I'm not sure exactly what kind"; it seems like one of those typical things that you will naturally stumble upon when using the Repository pattern and indeed when you start to separate out your query logic.

DetachedCriteria is an "offline" version of the NHibernate Criteria class, used to build up Criteria where an NHibernate Session is not available. The NHibernate documentation has more on how to use DetachedCriteria on its own, but I want to talk about inheriting from it to create a simple custom finder class.

Say we have a Active Record Person class, with height and weight properties:

[ActiveRecord]
public class Person : ActiveRecordBase
{
    [PrimaryKey]
    public int Id { get; set; }
    [Property]
    public int Height { get; set; }
    [Property]
    public int Weight { get; set; }
}

The height and weight properties are simplified, and I'm using C# 3.0 automatic properties for clarity. I want to search for a Person based on their height and weight, so to do so, I'll create a new finder class:

public class PersonFinder : DetachedCriteria
{
    public class PersonFinder(height, weight) : base(typeof(Person))
    {
         Add(Expression.Eq("Height", height));
         Add(Expression.Eq("Weight", weight));
    }
}

A simple class, but it clearly states its purpose. Here's how it could be used:

Person.FindAll(new PersonFinder(200, 300), new Order("Id", true));

For me, the advantage of this code isn't just in reducing what you have to type. Instead it is in the readability and discoverability of the code.