Specification Pattern Implementation

For some time now I’ve been willing to find a good implementation of the Specification Pattern. Information about this pattern can be found here:

http://en.wikipedia.org/wiki/Specification_pattern

interface ISpecification<TEntity>
{
	bool IsSatisfiedBy(TEntity item);
}

The idea I had was to use the IQueryable of Linq to query over large collections of objects and get all the benefits of delayed execution.

Recently I came across a blog post by Dennis Doomen who  did exactly that. Read about it here:

http://www.dennisdoomen.net/2010/10/my-silverlight-4-reference-architecture_12.html

That implementation gives me:

public class ActiveRegistrationsSpecification
{
	public IQueryable<Registration> SatisfyingElementsFrom
	(IQueryable<registration> registrations)
	{
		return registrations
			.Where(r => r.Status != AgreementStatus.Incomplete);
	}
}

What I ultimately wanted was an implementation that has both capabilities, to evaluate a single item and to get all items from a collection.

Today I found a very old blog post of Nicholas Blumhardt that did that:

http://nblumhardt.com/archives/implementing-the-specification-pattern-via-linq/

public abstract class Specification<T>
{
	public bool IsSatisfiedBy(T item)
	{
		return SatisfyingElementsFrom(new[] { item }.AsQueryable()).Any();
	}

	public abstract IQueryable<T> SatisfyingElementsFrom
	(IQueryable<T> candidates);
}

However this implementation has a downside as Nicholas Blumhardt already states:

“Unknown performance ramifications of AsQueryable() under heavy usage”

And he is right. The AsQueryable() usage is very slow compared to the normal IsSatisfiedBy method.

My idea to improve this implementation was to make the both methods use a Predicate. Of course this wasn’t all that easy, but after some testing I ended up with this very useful implementation:

 

public abstract class Specification<TEntity>
{
	protected Func<TEntity, bool> evalCompiled;
	protected Expression<Func<TEntity, bool>> evalExpression;

	internal Expression<Func<TEntity, bool>> Predicate
	{
		get
		{
			return evalExpression;
		}
		set
		{
			evalExpression = value;
			evalCompiled = evalExpression.Compile();
		}
	}

	public bool IsSatisfiedBy(TEntity item)
	{
		return evalCompiled(item);
	}

	public IQueryable<TEntity> SatisfyingElementsFrom
	(IQueryable<TEntity> candidates)
	{
		return candidates.Where(evalExpression);
	}
}

Next on my wishlist is to get a CompositeSpecification so I can combine specifications with And and Or or Negate a specification. I will keep you posted.

Cannot resolve the collation conflict…

Ever tried to do a join on text columns? Like this:

SELECT * from LocationAustralie la 
left join steps s on la.StepText = s.Value 

If your tables have different collations you get the error message:

Msg 468, Level 16, State 9, Line 2: Cannot resolve the collation
conflict between "Latin1_General_CI_AS" and 
"SQL_Latin1_General_CP1_CI_AS" in the equal to operation.

 

Two of my colleagues had this problem in a single week and asked whether I had a solution. I have…

So here is the solution: the keyword COLLATE.

Just add the collate to one of the columns on the join

SELECT * from LocationAustralie la
left join steps s on la.StepText = s.Value collate Latin1_General_CI_AS

Happy Querying!