LINQ Expressions, The Specification Pattern and Repositories
Disclaimer : I am unsure if what I am about to show here is a bridge too far in terms of bastardising the specification pattern ... it very well may be the case. However, Linq has provided a new paradigm that needs to be embraced, and sometimes that requires the tweaking of existing pratices and patterns.
Background Info
For some background on this article I recommend reading the following primers. I would never have to got to where I did without them. Please check out:
Implementing the Specification Pattern via Linq
[http://ubik.com.au/article/named/implementing_the_specification_pattern_with_linq]
Linq, the Specification Pattern and Encapsulation
[http://www.iridescence.no/post/Linq-the-Specification-Pattern-and-Encapsulation.aspx]
Implementing ORM-independent Linq queries
[http://rabdullin.com/implementing-orm-independent-linq-queries/]
The Goal
I wanted a flexible way to leverage the deferred execution power of Linq in my application. The logical place for this to occur was deep in the data access layer at the repository level. Also, as always, I wanted the ability to encapsulate my query logic into specifications and this became the real integration challenge with linq.
Specifications are easy to apply to existing in-memory collections - they fit that paradigm well. But at the lower level I knew linq could provide more power than what was previously possible with the traditional specification pattern. I wanted a way to leverage the deffered execution of Linq to drive my specifications for querying.
The Specification Class
My specification class is not dependent on any particular Linq to SQL provider. I chose to use Linq to NHibernate but that was a personal choice. I am quite sure that a switch to Linq-To-SQL would result in no modifications to any existing specifications. This provider agnostic specification implementation is a nice example of what a common language paradigm like Linq can provide.
Notice that the base abstract specification class handles all of the matching work for the specification. Any inheriting specification simply needs to specify their relevant MatchingCriteria. The SatisfyingElementFrom method (singular) simply enforces that a single result is returned. The bulk of the work is done in SatisfyingElementsFrom, which actually applies the criteria. Note that it is critical that the Matching criteria is of type Expression. This ensures we have access to the expression parsing power of Linq. Simply using a Func or a Predicate will break this implementation.
public abstract class Specification where T : IEntity
{
public abstract Expression> MatchingCriteria { get; }
public T SatisfyingElementFrom(IQueryable candidates)
{
return SatisfyingElementsFrom(candidates).Single();
}
public IQueryable SatisfyingElementsFrom(IQueryable candidates)
{
return candidates.Where(MatchingCriteria).AsQueryable();
}
}
A simple specification
Below is the code for a simple specification implementation. Notice how it has no responsibility apart from specifying the criteria that it represents.
public class PersonById : Specification
{
private readonly Guid id;
public PersonById(Guid id)
{
this.id = id;
}
public override Expression> MatchingCriteria
{
get { return p => p.Id == id; }
}
}
Conclusion
So far I have demonstrated how to implement specification classes that have the potential to harness the power of Linq. Please follow the other parts of the series to see further implementation details - specifically the repository.
Background Info
For some background on this article I recommend reading the following primers. I would never have to got to where I did without them. Please check out:
Implementing the Specification Pattern via Linq
[http://ubik.com.au/article/named/implementing_the_specification_pattern_with_linq]
Linq, the Specification Pattern and Encapsulation
[http://www.iridescence.no/post/Linq-the-Specification-Pattern-and-Encapsulation.aspx]
Implementing ORM-independent Linq queries
[http://rabdullin.com/implementing-orm-independent-linq-queries/]
The Goal
I wanted a flexible way to leverage the deferred execution power of Linq in my application. The logical place for this to occur was deep in the data access layer at the repository level. Also, as always, I wanted the ability to encapsulate my query logic into specifications and this became the real integration challenge with linq.
Specifications are easy to apply to existing in-memory collections - they fit that paradigm well. But at the lower level I knew linq could provide more power than what was previously possible with the traditional specification pattern. I wanted a way to leverage the deffered execution of Linq to drive my specifications for querying.
The Specification Class
My specification class is not dependent on any particular Linq to SQL provider. I chose to use Linq to NHibernate but that was a personal choice. I am quite sure that a switch to Linq-To-SQL would result in no modifications to any existing specifications. This provider agnostic specification implementation is a nice example of what a common language paradigm like Linq can provide.
Notice that the base abstract specification class handles all of the matching work for the specification. Any inheriting specification simply needs to specify their relevant MatchingCriteria. The SatisfyingElementFrom method (singular) simply enforces that a single result is returned. The bulk of the work is done in SatisfyingElementsFrom, which actually applies the criteria. Note that it is critical that the Matching criteria is of type Expression. This ensures we have access to the expression parsing power of Linq. Simply using a Func or a Predicate will break this implementation.
public abstract class Specification
{
public abstract Expression
public T SatisfyingElementFrom(IQueryable
{
return SatisfyingElementsFrom(candidates).Single();
}
public IQueryable
{
return candidates.Where(MatchingCriteria).AsQueryable();
}
}
A simple specification
Below is the code for a simple specification implementation. Notice how it has no responsibility apart from specifying the criteria that it represents.
public class PersonById : Specification
{
private readonly Guid id;
public PersonById(Guid id)
{
this.id = id;
}
public override Expression
{
get { return p => p.Id == id; }
}
}
Conclusion
So far I have demonstrated how to implement specification classes that have the potential to harness the power of Linq. Please follow the other parts of the series to see further implementation details - specifically the repository.
Comments