Ask a questionAsk a question
 

Answer'Invoke' LINQ expression type not supported

  • Thursday, May 01, 2008 2:57 PMSumo10 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hello there,

    I need to compose predicates together, and since this didn't make it into C# 3.0 in the end, I just wrote some of code relying on the nice Albahari PredicateBuilder.

    Unfortunately it looks like this is another one of those things supported in linq to sql but not in linq to entities.... The 'Invoke' expression type is not currently supported in ELinq.

    It seems I should be able to combine simple predicate expressions - perhaps there's a way which doesn't rely on Expression.Invoke?

    Any workarounds/pointers gratefully received!


Answers

All Replies

  • Friday, May 02, 2008 2:38 PMColin Meek Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    .NET 3.5 does support expression composition, but combining lambda expressions is a little bit trickier. Invoke provides a nice solution to the problem, but is not supported by LINQ to Entities. If possible, just chain Wheres or Unions, e.g.:

     

    Code Snippet

    public static IQueryable<T> And<T>(this IQueryable<T> query, params Expression<Func<T, bool>>[] predicates) {

        return predicates

            .Aggregate(query, (result, predicate) => result.Where(predicate));

    }

    public static IQueryable<T> Or<T>(this IQueryable<T> query, params Expression<Func<T, bool>>[] predicates) {

        return predicates

            .Aggregate(query.Where(t => false), (result, predicate) => result.Union(query.Where(predicate)));

    }

     

     

    Note that the union solution is relatively inefficient and does not necessarily produce the same results as an 'or' (duplicates in the source query are reduced to a single element in the result).

     

    Thanks,

    -Colin

     

    P.S. I'll post a more general solution to this problem in the next few days.
  • Friday, May 02, 2008 3:47 PMSumo10 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thanks Colin - This solution isn't what I'm after of course (i need a way of genuinely ORing linq predicates) ... but looking forward to your general solution!
  • Saturday, May 03, 2008 12:35 AMColin Meek Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    I've posted a more detailed response at:

     

    http://blogs.msdn.com/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx

     

    It outlines my first answer (above) and a couple of alternatives that have better performance.

     

    Thanks,

    -Colin

  • Thursday, May 08, 2008 11:32 AMSumo10 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thanks Colin! That looks wonderful. Now I have an excuse to take the time to understand the expressions api.
  • Thursday, May 08, 2008 3:41 PMNoam Ben-Ami - MSFTMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    To steal a phrase from one of our good friends, that blog post is Insanely Great!

     

  • Friday, May 09, 2008 1:06 PMSumo10 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I agree. It works like a charm. Exactly how will take me a while to figure out!

    A potential problem is the dependency on Matt Warren's ExpressionVisitor class. Matt teases that the real ExpressionVisitor may become public at some point - so in my own code I've fully-qualified the reference to it since System.Linq.Expressions is in scope.

    Are there any other versioning issues to be aware of? I want to avoid the possibility of anything breaking with some future .net release.

    I'm still hoping that predicate buliding will be included in C# and/or .net - I saw Anders say somewhere this was planned as a language feature at one point.

    Thanks again Colin.
  • Friday, February 20, 2009 7:56 PMSam2 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I am trying to copy the code in the link in the post marked as answer.
    When I try to compile this:

    public class ParameterRebinder : System.Linq.Expressions.ExpressionVisitor
    {

    I get: System.Linq.Expressions.ExpressionVisitor is inaccessable due to it's protection level.

    What to do??

    Thanks,

    Sam
  • Sunday, April 05, 2009 5:22 AMJoe AlbahariMVPUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I've now updated PredicateBuilder and LINQKit so that there's a turnkey solution for Entity Framework:

    http://www.albahari.com/nutshell/predicatebuilder.aspx

    Regards

    Joe
    Query databases interactively in LINQ - www.linqpad.net