Execute a linq tree expression into a where

c# entity-framework expression-trees linq

Question

This is my scenario: I need to extract data from an entity using an "OR" query on a a property in a linked entity.

These are my entities:

public class Dealer
{
  public virtual int id{get;set;}
  public virtual string name{get;set;}
  public virtual IList<Car> Cars{get;set;}
}

public class Car 
{
  public virtual int id{get;set;}
  public virtual string name{get;set;}
  public virtual int kw{get;set;}
}

Example: I want to extract all dealers that have cars with 98kw or 100kw. Sql Example:

SELECT Dealers.* FROM Dealers INNER JOIN Cars ON Cars.IdDealer = Dealers.Id WHERE Cars.kw = 98 OR Cars.kw = 100

I tried to use Expression trees but i don't know how to use them. I tried this:

var dealers = Session.Linq<Dealers>();
ParameterExpression pe = Expression.Parameter(typeof(int), "kw");
Expression tot = null;
var powers = new int[2]{98, 100};

for (var i = 0; i < powers.Length; i++)
{
    Expression right = Expression.Constant(int.Parse(powers[i]));
    if (i > 0)
        tot = Expression.Or(tot, Expression.Equal(pe, right));
    else
        tot = Expression.Equal(pe, right);
}
dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, null)));

but i get these compiler errors on the last row where I try to execute the Expression:

  • Cannot convert lambda expression to type string because it is not a delegate type
  • System.Collections.Generic.IList<Cars> does not contain a definition for Any and the best extension method overload System.Linq.Enumerable.Any(System.Collections.Generic.IEnumerable, System.Func) has some invalid arguments
  • Argument 2: cannot convert from System.Linq.Expressions.Expression<System.Func<Cars,bool>> to System.Func<Cars,bool>

Any suggestions?

Popular Answer

as per the comment that i left:

... can i make a little suggestion which may or may not be greeted with joy. in my opinion, you should avoid using RAW expressions in that fashion in an open environment. i would heartily suggest that you adopt a more closed approach and look at something like the albahari predicatebuilder: albahari.com/nutshell/predicatebuilder.aspx will save you lots of frustration. some great working examples on the page too

I can't emphasize enough the benefits that this has given many projects that we've undertaken. The usage of this library/approach translates to expressions along the lines of:

IQueryable<Product> SearchProducts (params string[] keywords)
{
  var predicate = PredicateBuilder.False<Product>();

  foreach (string keyword in keywords)
  {
    string temp = keyword;
    predicate = predicate.Or (p => p.Description.Contains (temp));
  }
  return dataContext.Products.Where (predicate);
}

etc. Thus, you can build pretty complex statements will all the internals hidden away. This makes complete sense, especially if you may have more junior devs working on the code now or in the future. I strongly urge you to indulge your curiousity and wander over to the link and get a better feel from there.



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why