Archive

Archive for December, 2008

Entity Framework and the Specification Pattern

December 22nd, 2008 Simon Segal 2 comments

A while back I posted a small framework for working with LINQ To SQL. This small set of libraries included a Repository pattern, coupled with the Specification Pattern and Fetching Strategies. In more recent times I decided that LINQ To SQL and the Entity Framework were just too close to warrant the investment in learning, understanding and using both, so to that end I decided to work those previous libraries into shape and refactor them for support of both OR/M products.

First up in this effort I chose to start with the refactor of the Specification interface and class implementation and that will be the item under discussion in this post.

Recently I remarked that the Entity Framework did not support Expression.Invoke() which made combining Specifications to form .Or and .And Specifications in the current version of the library unusable. After some discussion and comments from that previous post and some further investigation, I discovered an alternative that allowed removing the reliance on Invoking Expressions and enabled rewriting the .Or and .And behaviours of the Expression<T> via the magic of some utility classes with some very handy extension methods. Please take a look at Colin Meek’s post that explains and demonstrates the ‘rewriting’ solution and also recently pointed out that the Entity Framework Extensions library includes a way to resolve this issue, however I chose to utilise the other solution so my library did not form a dependency on the extensions library (for the moment).

the OLD Code:

   1: private class OrSpecification : Specification<T>
   2: {
   3:     private readonly ISpecification<T> left;
   4:     private readonly ISpecification<T> right;
   5:     public OrSpecification(ISpecification<T> left,ISpecification<T> right)
   6:     {
   7:         this.left = left;
   8:         this.right = right;
   9:
  10:         this._evalFunc =
  11:             (Func<T, bool>)Func<T, bool>.Combine
  12:             (left.EvalPredicate.Compile(),
  13:             right.EvalPredicate.Compile());
  14:
  15:         ParameterExpression parameter =
  16:             Expression.Parameter(typeof(T), “p”);
  17:         var invokedExpression =
  18:             Expression.Invoke(left.EvalPredicate,
  19:                 right.EvalPredicate.Parameters.Cast<Expression>());
  20:         _evalPredicate =
  21:             Expression.Lambda<Func<T, bool>>
  22:             (Expression.Or(right.EvalPredicate.Body,
  23:             invokedExpression), right.EvalPredicate.Parameters);
  24:     }
  25:     public override bool Matches(T entity)
  26:     {
  27:         return EvalPredicate.Compile().Invoke(entity);
  28:     }
  29: }

Line 18 is the offending line of code.

My NEW Code:

   1: private class OrSpecification : Specification<T>
   2: {
   3:     private readonly ISpecification<T> left;
   4:     private readonly ISpecification<T> right;
   5:     public OrSpecification(ISpecification<T> left,ISpecification<T> right)
   6:     {
   7:         this.left = left;
   8:         this.right = right;
   9:
  10:         this._evalFunc =
  11:             (Func<T, bool>)Func<T, bool>.Combine
  12:             (left.EvalPredicate.Compile(),
  13:             right.EvalPredicate.Compile());
  14:
  15:         _evalPredicate = left.EvalPredicate.Or(right.EvalPredicate);
  16:     }
  17:     public override bool Matches(T entity)
  18:     {
  19:         return EvalPredicate.Compile().Invoke(entity);
  20:     }
  21: }

In short, the extension methods in Colin’s post will kick in and rewrite the behaviour of the .And and .Or method avoiding the need to call Invoke(). This method of composing or ‘rewriting’ as Colin put’s it, also requires a copy of the ExpressionVisitor class which is internal to the Entity Framework. You can find a copy of the ExpressionVisitor here on the wayward blog.

So now I can use my specifications with the Entity Framework! For example if I wish to query my venerable Northwind database and ask for all the products that are now discontinued that are part of existing orders from customers in either Germany and the USA, I can write the following code:

   1: [Test()]
   2: public void RefineCombinedSpecifications()
   3: {
   4:     Specification<Customer> german_customer_spec =
   5:         new Specification<Customer>(c => c.Country == “Germany”);
   6:
   7:     Specification<Customer> us_customer_spec =
   8:         new Specification<Customer>(c => c.Country == “Usa”);
   9:
  10:     Specification<Product> ords_with_discontinued_prods =
  11:         new Specification<Product>(p => p is DiscontinuedProduct);
  12:
  13:     var comb_country_spec = (german_customer_spec | us_customer_spec);
  14:
  15:     using (var ctx = new NorthwindEntities())
  16:     {
  17:         var discontinued_products_on_order =
  18:             (ObjectQuery<Product>)
  19:             (from p in ctx.Products
  20:             .Where(ords_with_discontinued_prods.EvalPredicate)
  21:             from od in ctx.OrderDetails
  22:             from o in ctx.Orders
  23:             from c in ctx.Customers
  24:             .Where(comb_country_spec.EvalPredicate)
  25:             where od.ProductID == p.ProductID &&
  26:                   o.OrderID == od.OrderID &&
  27:                   c.CustomerID == o.Customer.CustomerID
  28:             select p).Distinct();
  29:
  30:         Console.WriteLine(discontinued_products_on_order.ToTraceString());
  31:
  32:         foreach (var product in discontinued_products_on_order)
  33:         {
  34:             Console.WriteLine(“The product ID is {0} with a name of {1}”,
  35:                 product.ProductID, product.ProductName);
  36:         }
  37:     }
  38:
  39:     Console.ReadLine();
  40: }

What’s the benefit you ask? Well the specification class offers me both equality testing (check out the matches method in the download), dynamic querying and and injection as demonstrated in the Repository pattern as here. Next up I will look at flipping open the Repository pattern so it supports LINQ To SQL and the Entity Framework and when the Repository and the Fetching Strategies have been refactored I will post a completely updated version.

Share/Save/Bookmark

Good practice skills vs. Technology skills - which should I choose.

December 21st, 2008 Simon Segal No comments

Something that intrigues me is the very nature of the way software development skills are rated. It’s not altogether unheard of that the more technology specific stuff you put into your resume the better understood or rather perceived you might be and the more design and practice oriented stuff you put in that resume, may find you perceived all the more esoteric.

I am pretty sure that too much attention in my resume given to practices such as DDD and DI /IoC amongst other things, has been been perceived as fringe and understanding of their value was getting lost in some cases. Typically employers and recruiters are often more interested in how many years of Ajax, ASP.Net, Web Services, ADO.Net etc that you have and I should point out that this is not a criticism of either merely an observation; it comes down to the individual to demonstrate what indeed the value of such knowledge and skills are to any relevant interested party.

So basically I guess my point is this, if your constantly finding yourself perplexedsupport_structure by  what skill you need next, then perhaps you should look at the outlying aspects rather than the obvious and make sure that you give some time to practices or learning new patterns that will help improve the quality of your work regardless of your technology choices. I should point out that whilst many would consider Inversion of Control a technology (I use IoC as an example here), I consider it more a methodology or design practice for the sake of this post and demonstrating the point I am trying to make.

So rather than worry about WCF or WF 4.0 or some other fancy PDC 2008 technology today, perhaps look at Castle Windsor or Spring.Net and begin to get to grips with how DI / IoC can help you write better software or even buy Jimmy Nilsson or Eric Evans books and have a look at Domain Driven Design and see what you can learn from that approach - a wise man once told me "it’s not always about the latest tech!"

PS: I am not saying you should ignore new things as a matter of course (I plan to look at Oslo and M in the coming months myself) but try to balance and give some priority to assigning value to that of the here and now!

Share/Save/Bookmark

Narrowing ORM options for the sake of sanity

December 17th, 2008 Simon Segal 6 comments

"The right tool for the job" or so the saying goes which I don’t believe can be applied to a choice between LINQ to SQL and the Entity Framework.  Currently I am evaluating the virtues of Entity Framework over LINQ Tochoices SQL; why not use both I hear you say? Well I have already reached the point in the evaluation to know that there is not enough separating them to make me consider maintaining skills in both and considering that all Microsoft’s serious investment is going into the Entity Framework then the choice is made that much easier.

I have found to date that I can continue with using the Repository approach along with the Specification Pattern (for dynamic querying) and Fetching Strategies and that was a big criteria for me. There are of course some lingering frustrations with Version 1.0 however at this point I am satisfied that the Entity Framework team will address those in subsequent releases and for the moment I will endure.

Share/Save/Bookmark

Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia