Archive

Posts Tagged ‘LINQ To SQL’

More Entity Framework frustration [I want my Specification Pattern].

December 15th, 2008 Simon Segal 7 comments

A while back I posted about LINQ To SQL and how to implement the specification pattern and fetching strategies with a IRepository. Since then you may have heard the announcements and followed the ensuing debate about the future of LINQ To SQL. On reflection I have since decided to explore EF as fully as possible and prepare for knowing it deeply, particularly as it promises to embody values such as support of POCO and Lazy Loading which are some of things I am not prepared to live without.

In the meantime I thought it was worth taking the same approach as I had with LINQ To SQL and see what was possible with respect to implementing the Specification Pattern in order to provide dynamic querying ability (minus the repository - for the moment only).

Let’s start with a given Entity Model:

ef_spec_model

I am not going to use much of this model for the purpose of this post but some time soon I will look at how to implement a Fetching Strategies with Entity Framework in a similar manner as that which I demonstrated with LINQ To SQL, but let’s move forward with the specification patterns for now.

So given my model has Orders which aggregate Order_Details and Orders may contain discontinued products I might hypothetically want to sum the total of my unfulfilled problem orders where they contain discontinued products. If I just whip out my specification library (built for LINQ’ish entity / object matching and LINQ To SQL dynamic querying) and I attempt to use it directly with the Entity Framework in this fashion, I get the same behaviour as I expected previously with the other technologies.

static void Main(string[] args)
{
    Specification<Order> order_spec =
        new Specification<Order>(o => o.Order_Details.All
            (od => od.Product is DiscontinuedProduct));

    using (var ctx = new NorthwindEntities())
    {
        ObjectQuery<Order> orders =
            (ObjectQuery<Order>)
            from o in ctx.Orders
                .Include(“Order_Details”)
                .Include(“Customer”)
            .Where(order_spec.EvalPredicate)
            select o;

        Console.WriteLine(orders.ToTraceString());

        try
        {
            foreach (var order in orders)
            {
                var sumup =
                    order.Order_Details.Sum
                    (od => od.Quantity * od.UnitPrice);
                Console.WriteLine(sumup.ToString());
            }
        }
        catch (ArgumentException argEx)
        {
            Console.WriteLine(argEx.Message);
        }
    }

    Console.ReadLine();
}

Ok, that’s great but now I want to try combining specifications which I can do by taking advantage of the operator overloading for OR and AND. Bam, crash it comes tumbling down.

Now its late and I am starting to get annoyed with the Entity Framework. As it turns out (as far as I can tell), LINQ to SQL is far more pliable in managing dynamic queries. Why? Well EF doesn’t play nice with Expression<T>, specifically Expression<Func<T>> etc. Errors arise when you build and invoke Expressions because the Entity Framework doesn’t support Expression.Invoke which is required to combine Expressions.

private class OrSpecification : Specification<T>
{
    private readonly ISpecification<T> left;
    private readonly ISpecification<T> right;
    public OrSpecification(ISpecification<T> left, ISpecification<T> right)
    {
        this.left = left;
        this.right = right;

        this._evalFunc =
            (Func<T, bool>)Func<T, bool>.Combine
            (left.EvalPredicate.Compile(),
            right.EvalPredicate.Compile());

        ParameterExpression parameter =
            Expression.Parameter(typeof(T), “p”);
        var invokedExpression =
            Expression.Invoke(left.EvalPredicate,
                right.EvalPredicate.Parameters.Cast<Expression>());
        _evalPredicate =
            Expression.Lambda<Func<T, bool>>
            (Expression.Or(right.EvalPredicate.Body,
            invokedExpression), right.EvalPredicate.Parameters);
    }
    public override bool Matches(T entity)
    {
        return EvalPredicate.Compile().Invoke(entity);
    }
}
The problem with the Specification as it is now, is that it fails when we combine Specifications into an OrSpecification or AndSpecification. You might notice that I added the _evalFunc member, this was an attempt to to use the overload of IQueryable<T>.Where that takes a Func<T> as the argument rather than the Expression<Func<T>> ; this approach work’s to a degree but you lose the ability to cast IQueryable<T> to ObjectQuery<T>. The other thing that I find enormously frustrating is that LINQ To Entity queries return’s a WhereSelectEnumerableIterator if I use the overloaded version of the Where extension method that takes the Func<T> as it’s argument and this means I am unable to cast it to ObjectQuery<T> which constricts our options in moving that strategy forward.
private static void CombinedOrSpecExample()
{
    Specification<Order> order_spec =
        new Specification<Order>(o => o.Order_Details.All
            (od => od.Product is DiscontinuedProduct));

    Specification<Order> german_customer_spec =
        new Specification<Order>(c => c.Customer.Country == “Germany”);

    var orSpec = order_spec | german_customer_spec;

    using (var ctx = new NorthwindEntities())
    {
        var orders =
            (ObjectQuery<Order>)
            from o in ctx.Orders
                .Include(“Order_Details”)
                .Include(“Customer”)
            .Where(orSpec.EvalFunc).AsQueryable<Order>()
             select o;

        Console.WriteLine(orders.ToTraceString());

        try
        {
            foreach (var order in orders)
            {
                var sumup =
                    order.Order_Details.Sum
                    (od => od.Quantity * od.UnitPrice);
                Console.WriteLine(“The sum of orders for order ID: {0} is {1}”,
                    order.OrderID.ToString(), sumup.ToString());
            }
        }
        catch (ArgumentException argEx)
        {
            Console.WriteLine(argEx.Message);
        }
    }
}

This code produces a casting error:

ef_specpattern_error_enumerable

which is as already stated, related to the issue created by using the .Where extension method that accepts a Func<T> as opposed to the Expression<Func<T, bool>>.
As I said it’s late and so far I have a big headache but I will persist.

Share/Save/Bookmark

Entity Framework - Learning Materials recommended.

December 9th, 2008 Simon Segal 7 comments

To date the best first up learning materials I have come across for EF have been the DNR TV web casts with Dan Simmons and Julia Lerman’s tutorials which I posted a PDF consolidation of recently. Dan Simmons gives some very good rudimentary ‘meet the Entity Framework’ demonstrations and I am beginning to quickly feel at home with EF. Having said that I will add my initial observations on the product so far (bear in mind I was a huge fan of LINQ To SQL).

  • A better and more functional designer experience than LINQ to SQL
  • Lacks the POCO ability that I crave (perhaps in V 2.x something)
  • I like having the ability to map single entities to multiple tables, which LINQ To SQL could not do.
  • Curiously, I have found that EF supports rapid development scenarios with an extremely similar approach to that of LINQ To SQL, therefore the argument to use LINQ TO SQL if your in a ‘hurry’ doesn’t really stack up for me anymore and I am questioning the validity of that proposal altogether.

Find the DNR TV episodes here:

Episode 1

Episode 2

To get more deeply into the product I just now ordered Julia’s book which I will have to wait till Jan 2009 for but there’s plenty to do whilst waiting, I am going to have a go at getting the specification pattern working with the Entity Framework as I did with LINQ to SQL previously and think about how to deal nicely with Fetching Strategies in EF.

Share/Save/Bookmark

LINQ To SQL dead? Raise the damn building!

November 1st, 2008 Simon Segal 2 comments

l2sobjections So we don’t need another blogger starting a discussion as too whether it’s the case or not but what I would like to say is this: if it’s true I would like to hear a full and clear explanation as to the reasons why they killed off L2S, it’s the least we deserve! If the suggestions are correct and this announcement is indeed a subtle notice of the long term plans to shelve L2S, then have the guts to say so clear and out loud, perhaps my previous sentiments were off course and I should apologisegoat_tongue to the signatories of the ‘you know what’ for behaving as indelicately as the accused would seem to be behaving here! I have personally invested quite some time into L2S and as a long standing developer on the MS platform I expect to be treated with a touch more respect than a veiled notice such as this. I can only hope that everyone suggesting L2S has died are terribly wrong and I would be thrilled to see MS make an speedy announcement to the contrary of the rumour to squash it good and quick. LINQ To SQL - Live Long and Prosper.

UPDATE: Daniel G posted this recently with some explanation, which doesn’t exactly thrill me either. No offence to Daniel but this is the equivalent of a developer in my organisation making product announcements to our clients. It does however support the notion that ‘meaningful’ progression of LINQ to SQL is not a discussion point for the future and the choices in picking your poison just got reduced by a one.

Final Update:

Tim has posted some clarification which seems to be reasonably clear on the subject. So how many ORM/s should we learn? I look forward to seeing how much of the so-called ‘not about ORM’ bits in EF are important to me. It’s time to start investing some time in EF!

Share/Save/Bookmark

Categories: LINQ To SQL, ORM Tags: ,
Creative Commons Attribution-ShareAlike 2.5 Australia
Creative Commons Attribution-ShareAlike 2.5 Australia