Reputation: 82467
I am trying to make a modular Linq query (to an OData source).
This is a simplified version of my query:
// Any clause that I want to be modular
Func<Encounter, bool> orderAnyClause = x => x.OrderName.StartsWith("Order 00");
// Query using the any clause
var result = entities.Customers.Where(cust=> cust.Orders.Any(orderAnyClause));
// A method to do the selection. It works just fine.
IQueryable<SearchSelectionResult> selectedResults = SelectResults(result);
// This throws the exception shown below
var list = selectedResults.ToList();
This all compiles fine, but when I run it my any clause causes this exception:
Unable to cast object of type 'System.Linq.Expressions.ConstantExpression' to type 'System.Linq.Expressions.LambdaExpression'.
I know it is my any clause because if I embed the the clause in the statement, it all works fine.
Why am I getting this error? And how can I break this statement out and not get the error?
Update: Using an Expression
I tried to use an expression like this:
Expression<Func<Encounter, bool>> orderAnyClause =
x => x.OrderName.StartsWith("Order 00");
And I get the following compile time error message:
Instance argument: cannot convert from System.Data.Services.Client.DataServiceCollection<ODataComponetizedQueriesTest.MyEntities.Order>' to 'System.Linq.IQueryable<ODataComponetizedQueriesTest.MyEntities.Order>'
Upvotes: 0
Views: 673
Reputation: 133
You could try defining orderAnyClause like this:
Expression<Func<Encounter, bool>> orderAnyClause =
x => x.OrderName.StartsWith("Order 00");
I didn't test it, but the way query comprehension works (and based on the error), it wouldn't be able to do anything with it unless it gets it as an expression.
Upvotes: 5
Reputation: 1502825
Your IQueryable
needs to work with expression trees in order to convert the query - in other words, it needs to have a view of the code as data, rather than just as executable code.
Now I'm not 100% sure this will work, but I'd hope that you could use:
Expression<Func<Encounter, bool>> orderAnyClause =
x => x.OrderName.StartsWith("Order 00");
... and then keep the same code. That way your orderByClause
variable refers to an expression tree, not a delegate. Now it's possible that that won't work - because you're using it in another lambda expression here:
cust => cust.Orders.Any(orderAnyClause)
... and that lambda expression will also be converted to an expression tree. It really depends on what the OData provider does with it. You may need to write a method to do funky stuff to build up the cust.Orders.Any(orderAnyClause)
- but it's worth trying the simple way first.
Upvotes: 0