It is a creative effort to chain predicates and too bad it does not work. The reason why has been explained excellently by Lasse and Nicholas (+2). But you also ask:
Anyone got a better suggestion?
The drawback of compiled expressions is that they're not expressions any more and thus, can't be used with IQueryable
s that are backed by SQL query providers (like linq to sql or linq to entities). I assume _repo.Customers
is such an IQueryable
.
If you want to chain expressions dynamically, LINQKit's PredicateBuilder is an excellent tool to do this.
var pred = Predicate.True<Customer>();
pred = pred.And(c => c.lastname.Equals(_customer.lastName, StringComparison.InvariantCultureIgnoreCase);
pred = pred.And(c => c.firstname.Equals(_customer.firstName, StringComparison.InvariantCultureIgnoreCase);
pred = pred.And(c => c.DOB.ToString("yyyyMMdd").Equals(_customer.DOB.ToString("yyyyMMdd"));
var customersFound = _repo.Customers.Where(pred.Expand());
This is what the Expand
is for:
Entity Framework's query processing pipeline cannot handle invocation expressions, which is why you need to call AsExpandable on the first object in the query. By calling AsExpandable, you activate LINQKit's expression visitor class which substitutes invocation expressions with simpler constructs that Entity Framework can understand.
Or: without it an expression is Invoke
d, which causes an exception in EF:
The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
BTW. If you use linq to sql/entities you may as well use c.lastname == _customer.lastName
because it is translated into SQL and the database collation will determine case sensitiveness.