1

I'm consuming an Odata v4 service using Odata Client Code generator proxy class.

MetroContext = new MetroContainer(new Uri(@"http://localhost:56222/service"));
IQueryable<Patient> query = MetroContext.Patients;
query = query.Where(x => x.FirstName == "john");

Above code is working fine. But I need to build queries dynamically. So I have tried following:

MetroContext = new MetroContainer(new Uri(@"http://localhost:56222/service"));
IQueryable<Patient> query = MetroContext.Patients;

ParameterExpression pe = Expression.Parameter(typeof(Patient), "patient");
Expression left = Expression.Property(pe, "FirstName");
Expression right = Expression.Constant("john");
Expression predicateBody = Expression.Equal(left, right);

query = query.Provider.CreateQuery<Patient>(predicateBody);

When I run the program I'm getting an error message:

Error translating Linq expression to URI: The binary operator 'Equal' is not supported.

  • Why I'm getting this error and how can I solve this?
  • How can I create dynamic queries by combining methods such as Contains() , StartsWith() ?
Rahul
  • 2,431
  • 3
  • 35
  • 77

1 Answers1

2

I can't test that specific query provider, but at the first place predicateBody is not a valid expression for any provider.

Instead, you need to build Expression<Func<Patient, bool>> expression and pass it to the Where method like this:

// ...
var predicate = Expression.Lambda<Func<Patient, bool>>(predicateBody, pe);
query = query.Where(predicate);

What about your second question, you need to use some of the Expression.Call overloads. For instance:

Expression predicateBody = Expression.Call(left, "Contains", null, right);

Similar for "StartsWith" and "EndWith" etc.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • thanks, it's working perfectly. One more question, Can I use `Equal`, `GreaterThan` comparison in `Expression.Call()` method? – Rahul Mar 29 '16 at 19:59
  • No. `Call` is for methods. But of course you can use `Equal`, `GreaterThan` etc. in method arguments (for conditions). Do you have a specific example? – Ivan Stoev Mar 29 '16 at 20:03
  • Can I replace the code `Expression.NotEqual(left, right)` with something like `Expression.Call(left, "NotEqual", null, right)` ? – Rahul Mar 29 '16 at 20:08
  • No. These are operators, not methods. – Ivan Stoev Mar 29 '16 at 20:09
  • Ok, now I understand. Thanks. – Rahul Mar 29 '16 at 20:10
  • Does this work with dynamically generating "OR" expressions? Trying to loop through some collection objects to generate OR's and having problems with a normal predicatebuilder. – Matt Sep 26 '16 at 20:35
  • 1
    @Matt Not sure exactly about the question. If you have problems with the "normal" PredicateBuilder, you might check my answer to [Establish a link between two lists in linq to entities where clause](http://stackoverflow.com/questions/36246162/establish-a-link-between-two-lists-in-linq-to-entities-where-clause/36247259#36247259) or the [Universal PredicateBuilder](https://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/) – Ivan Stoev Sep 26 '16 at 20:53
  • Shucking perfect. Thanks! – Matt Sep 26 '16 at 21:38