Building Query Expressions
So far, when we’ve needed to dynamically compose queries, we’ve done so by conditionally chaining query operators. Although this is adequate in many scenarios, sometimes you need to work at a more granular level and dynamically compose the lambda expressions that feed the operators.
In this section, we’ll assume the following Product class:
[Table] public partial class Product
{
[Column(IsPrimaryKey=true)] public int ID;
[Column] public string Description;
[Column] public bool Discontinued;
[Column] public DateTime LastSale;
}Delegates Versus Expression Trees
Recall that:
Local queries, which use
Enumerableoperators, take delegates.Interpreted queries, which use
Queryableoperators, take expression trees.
We can see this by comparing the signature of the Where operator in Enumerable and Queryable:
public static IEnumerable<TSource> Where<TSource> (thisIEnumerable<TSource> source, Func<TSource,bool> predicate) public static IQueryable<TSource> Where<TSource> (thisIQueryable<TSource> source,Expression<Func<TSource,bool>> predicate)
When embedded within a query, a lambda expression looks
identical whether it binds to Enumerable ’s operators or Queryable ’s operators:
IEnumerable<Product> q1 = localProducts.Where (p => !p.Discontinued); IQueryable<Product> q2 = sqlProducts.Where (p => !p.Discontinued);
When you assign a lambda expression to an intermediate variable,
however, you must be explicit about whether to resolve to a delegate
(i.e., Func<>) or an expression ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access