Applying AOP on IQueryables

05.05.2010 20:49Comments
When working with LinqToSql or Entity Framework, you will be using IQueryables extensibly. So extensibly, that plenty of your code will be employed in writting Where clauses in Linq. Linq makes it very easy and declarative to ask for whatever you need. The problem araises when you have  complex where clauses and the same conditions all over your repository. For example, suppose your records have a DateDeleted column, which means that the record has been deleted when it is not null (e => e.DateDeleted != null). You could have that condition all over the place. And a similar thing would happen if you had a IsActive, or Status columns. The proposed solution is very simple, we use method extensions in order to add the most common conditions to the IQueryable<T>. Something like this: public static IQueryable<Order> ThatAreShipped(this IQueryable<Order> query) { return query.Where(o => o.Status == OrderStatus.Shipped); } or public static IQueryable<Order> WhereIdIs(this IQueryable<Order> query, int id) { return query.Where(o => o.Id == id); } So you can see a simple pattern, when the condition requires parameters, we use the prefix "Where", and when the condition doesn't require a parameter, then we use the prefix "That". So we could see something like the following and easily understand what we will get in return: var orders = context.Orders.ThatAreShipped().WhereTotalGreaterThan(100).WhereShippingStateIs("NY"); The basic AOP concept we are avoiding here is to have similar code Scattered all over our repository. It turns out that method extensions, are an excellent and easy way to apply AOP. If you use the namespace of these extensions to be internal to the repository, then you will see this methods in the repository only. So if you do the following from outside the repository namespace: var orders = new List<Order>().AsQueryable().ThatAreShipped() This would throw a compilation error, and that is perfect, because it is a repository concern only.

comments powered by Disqus