In my previous post I put down some thoughts on the Repository and Specification patterns and in the end said that with the introduction of Linq and the growing popularity of ORM frameworks and their support for Linq, it’s time to look back at these two patterns and see how we can leverage Linq to simplify the patterns and make them infrastructure agnostic.
The goal of this post is to implement infrastructure for a Repository and Specification pattern that achieves the following goals:
- We should be able to execute Linq queries directly against the repository.
- Implement a specification pattern that allows us to use Expressions as predicates for the specifications.
- Implement a specification pattern than allows us to combine specifications (Composite Specification Pattern)
- We should be able to query the repository using the Specification pattern.
- We should be able to execute Linq queries against the repository directly and also combine the query with specifications.
Creating a base class for all Repositories:
With the above goals the first thing is to start implementing a base Repository interface:
public interface IRepository<T> : IQueryable<T>
{
void Save(T entity);
void Remove(T entity);
}
The IRepository interface also implements the IQueryable interface allowing us to execute Linq queries directly on the repository. Most repository implementations also have a Load or a Get method that takes in an ID that the repository uses to load the entity. In this case I have omitted those functions since they can be easily represented by Linq queries.
The next step is to implement an abstract base class to make it easy for creating different implementations of the IRepository interface:
public abstract class RepositoryBase<T> : IRepository<T>
{
}
So the first thing is to add the Save and Remove methods to the RepositoryBase class as abstract methods. This will allow the child classes to implement the actual functionality of Saving and Removing the entities from the repository:
#region Implementation of IRepository<T>
public abstract void Save(T entity);
public abstract void Remove(T entity);
#endregion
Next we add abstract property to the base class allowing the child class to pass in a IQueryable instance that the base class will use to implement the IQuerable interface:
public abstract class RepositoryBase<T> : IRepository<T>
{
protected abstract IQueryable<T> RepositoryQuery { get;}
Now we can implement members of the IQueryable interface and basically just delegate the calls for IQueryable to the IQuerable isntance that the RepositoryQuery provides us:
#region Implementation of IEnumerable
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<T> GetEnumerator()
{
return RepositoryQuery.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return RepositoryQuery.GetEnumerator();
}
#endregion
#region Implementation of IQueryable
/// <summary>
/// Gets the expression tree that is associated with the instance of <see cref="T:System.Linq.IQueryable" />.
/// </summary>
/// <returns>
/// The <see cref="T:System.Linq.Expressions.Expression" /> that is associated with this instance of <see cref="T:System.Linq.IQueryable" />.
/// </returns>
public Expression Expression
{
get { return RepositoryQuery.Expression; }
}
/// <summary>
/// Gets the type of the element(s) that are returned when the expression tree associated with this instance of <see cref="T:System.Linq.IQueryable" /> is executed.
/// </summary>
/// <returns>
/// A <see cref="T:System.Type" /> that represents the type of the element(s) that are returned when the expression tree associated with this object is executed.
/// </returns>
public Type ElementType
{
get { return RepositoryQuery.ElementType; }
}
/// <summary>
/// Gets the query provider that is associated with this data source.
/// </summary>
/// <returns>
/// The <see cref="T:System.Linq.IQueryProvider" /> that is associated with this data source.
/// </returns>
public IQueryProvider Provider
{
get { return RepositoryQuery.Provider; }
}
#endregion
Here’s the full code for the RepositoryBase class:
public abstract class RepositoryBase<T> : IRepository<T>
{
protected abstract IQueryable<T> RepositoryQuery { get;}
#region Implementation of IRepository<T>
public abstract void Save(T entity);
public abstract void Remove(T entity);
#endregion
#region Implementation of IEnumerable
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<T> GetEnumerator()
{
return RepositoryQuery.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return RepositoryQuery.GetEnumerator();
}
#endregion
#region Implementation of IQueryable
/// <summary>
/// Gets the expression tree that is associated with the instance of <see cref="T:System.Linq.IQueryable" />.
/// </summary>
/// <returns>
/// The <see cref="T:System.Linq.Expressions.Expression" /> that is associated with this instance of <see cref="T:System.Linq.IQueryable" />.
/// </returns>
public Expression Expression
{
get { return RepositoryQuery.Expression; }
}
/// <summary>
/// Gets the type of the element(s) that are returned when the expression tree associated with this instance of <see cref="T:System.Linq.IQueryable" /> is executed.
/// </summary>
/// <returns>
/// A <see cref="T:System.Type" /> that represents the type of the element(s) that are returned when the expression tree associated with this object is executed.
/// </returns>
public Type ElementType
{
get { return RepositoryQuery.ElementType; }
}
/// <summary>
/// Gets the query provider that is associated with this data source.
/// </summary>
/// <returns>
/// The <see cref="T:System.Linq.IQueryProvider" /> that is associated with this data source.
/// </returns>
public IQueryProvider Provider
{
get { return RepositoryQuery.Provider; }
}
#endregion
}
We can now use this base class to implement child classes and meet our first requirement where we should be able to execute Linq queries directly on the repository. Below are two implementations, one is a Repository that uses a In memory list of Persons while another is a repository that uses a Linq to SQL DataContext (Note: Ideally the DataContext should not be created by the Repository but instead it should either get the DataContext through dependency injection or through a service locator, but for this example creating the DataContext should suffice):
public class InMemoryPersonRepository : RepositoryBase<Person>
{
private List<Person> _persons = new List<Person>();
#region Overrides of RepositoryBase<Person>
protected override IQueryable<Person> RepositoryQuery
{
get { return _persons.AsQueryable(); }
}
public override void Save(Person entity)
{
_persons.Add(entity);
}
public override void Remove(Person entity)
{
_persons.Remove(entity);
}
#endregion
}
public class LinSqlPersonRepository : RepositoryBase<Person>
{
private ClassScheduleDataContext _context = new ClassScheduleDataContext();
#region Overrides of RepositoryBase<Person>
protected override IQueryable<Person> RepositoryQuery
{
get { return _context.Persons.AsQueryable(); }
}
public override void Save(Person entity)
{
_context.Persons.InsertOnSubmit(entity);
}
public override void Remove(Person entity)
{
_context.Persons.DeleteOnSubmit(entity);
}
#endregion
}
So now it’s fairly simple to execute Linq queries directly on the repository:
public static void Main(string[] args)
{
IRepository <Person> repository = new InMemoryPersonRepository();
var results = from person in repository
where person.LastName.Contains("Doe")
select person;
}
Creating a Specification class that allows using Expressions as predicates:
Okay, the next three requirements deal with implementing a Specification pattern that will allow us to use Lambda expressions as predicate. So starting with the interface:
public interface ISpecification<T>
{
Expression<Func<T, bool>> Predicate { get; }
bool IsSatisfiedBy(T entity);
}
The ISpecificaiton interface has one property Predicate that should return the expression that the specification uses. Now that we have an interface, lets create a generic Specification class that allows creating specification instances:
public class Specification<T> : ISpecification<T>
{
private readonly Expression<Func<T, bool>> _predicate;
public Specification(Expression<Func<T, bool>> predicate)
{
_predicate = predicate;
}
public Expression<Func<T, bool>> Predicate
{
get { return _predicate; }
}
public bool IsSatisfiedBy(T entity)
{
return _predicate.Compile().Invoke(entity);
}
}
So far so good… the Specification class basically takes in an Expression of Func<T, bool> that it stores in the _predicate field, which it then invokes in IsSatisfiedBy to check if a entity satisfies the specification. Now the third requirement is to allow composing specifications. To provide a clean framework, I’m going to use some operator overloading logic and overload the & and | operators on Specification class:
public static Specification<T> operator & (Specification<T> leftSide, Specification<T> rightSide)
{
var rightInvoke = Expression.Invoke(rightSide.Predicate, leftSide.Predicate.Parameters.Cast<Expression>());
var newExpression = Expression.MakeBinary(ExpressionType.AndAlso, leftSide.Predicate.Body, rightInvoke);
return new Specification<T>(
Expression.Lambda<Func<T, bool>>(newExpression, leftSide.Predicate.Parameters)
);
}
public static Specification<T> operator | (Specification<T> leftSide, Specification<T> rightSide)
{
var rightInvoke = Expression.Invoke(rightSide.Predicate, leftSide.Predicate.Parameters.Cast<Expression>());
var newExpression = Expression.MakeBinary(ExpressionType.OrElse, leftSide.Predicate.Body, rightInvoke);
return new Specification<T>(
Expression.Lambda<Func<T, bool>>(newExpression, leftSide.Predicate.Parameters)
);
}
What the overloads does is it takes two specifications that need to be combined and creates a new BinaryExpression of the appropriate expression type, that is OrElse or AndAlso, and then returns a new Specification that uses the BinaryExpression as it’s predicate. We can now use the Specification class like so to define our specifications:
public class CustomerSpecifications
{
public Specification<Customer> IsPreferred
{
get
{
return new Specification<customer>(customer => customer.AverageInvoice > 100000 &&
customer.AverageQty > 1000);
}
}
public Specification<Customer> BuysPremiumPaper
{
get
{
return new Specification<Customer>(customer => customer.PaperOrdered
.Where(paper => paper.Premium == true)
.Count() > 100);
}
}
}
And use the above specifications in a Customer entity like so:
public class Customer
{
public bool IsPreferredAndBuysPremium
{
get
{
return (CustomerSpecifications.IsPreferred &
CustomerSpecifications.BuysPremiumPaper).IsSatisfiedBy(this);
}
}
}
Integrating the Specification class with RepositoryBase:
Now that we have a way to define re-usable business logic by the way of specifications, lets integrate the Specification class with the RepositoryBase class to allow querying the repository using specifications. First thing is to modify the IRepository interface and add a Query method to it so that returns an IQueryable based on executing the provided specification:
public interface IRepository<T> : IQueryable<T>
{
void Save(T entity);
void Remove(T entity);
IQueryable<T> Query(ISpecification<T> specification);
}
Next is to implement the Query method on the RepositoryBase class:
public IQueryable<T> Query(ISpecification<T> specification)
{
return RepositoryQuery.Where(specification.Predicate);
}
What the Query implementation does is basically uses the Where Linq extension to add the predicate provided by the specification to the IQueryable instance. Now with that done the last two requirements are also complete. Below is an example that shows the various ways we can now use the RepositoryBase and Specification classes to query the repository flexibly:
public static void Main(string[] args)
{
var allCustomersInStateCA = from customer in new CustomersRepository()
where customer.State == "CA"
select customer;
var preferredCustomers = new CustomerRepository.Query(CustomerSpecifications.IsPreferred);
var preferredCustomersInCA = from customer in preferredCustomers
where customer.State == "CA"
select customer;
var prefferedPremiumCustomers = new CustomerRepository().Query(CustomerSpecifications.IsPreferred &
CustomerSpecifications.BuysPremiumPaper);
var prefferedPremimumCustomersInCA = from customer in prefferedPremiumCustomers
where customer.State == "CA"
select customer;
}
The above implementation now satisfies all the goals I had set out for the Repository and Specification implementation. I’ve added similar implementations to Rhinestone, so if you would like to get complete source code of the RepositoryBase and Specification classes check out Rhinestone’s source code: http://code.google.com/p/rhinestone/source/checkout.