3

I am using PredicateBuilder and Colin Meek's equivalent to compose predicates in an WCF Data Services friendly (i.e. no invocation expressions etc.) way. These work for some queries but fail with "Recursion reached allowed limit" as the query complexity increases. Unfortunately, this limit is below what I expect in normal circumstances in my code. I'm also unable to determine beforehand when this limit is reached.

Is is possible to:

  • simplify predicates before they hit WCF Data Services?
  • determine when query complexity exceeds the limit for WCF Data Services?

In my code, I'm building a predicate for Azure Data Market services that accept 'state' and 'city' parameters. Rather than issue a call for each city*state pairing, I'm composing a predicate along the lines of:

((city eq City11 or city eq City12 ...or city eq City1N) and (state eq State1))
...
or
((city eq CityM1...) and (state eq StateM))

Because of the expression tree, in actuality the predicate would be more like this:

((false or (((false or (City eq City11)) or (City eq City12)) and (State eq State1))) or (((false or (City eq City21)) or (City eq City22)) and (State eq State2)))

Using LINQPad I can capture the request, manually simplify it and prove that these work once simpified. Because no simpification is attempted by my code, the OData query that hits Azure Data Services is overly complex/recursive and generates the exception. In outline above, I apply the simplifications such as (x or y) or z == x or y or z and this has the effect of reducing the complexity of the query sufficiently that it passes muster. Hence my two questions above.

Any help/pointers would be very much appreciated!

DazWilkin
  • 32,823
  • 5
  • 47
  • 88
  • I don't know PredicateBuilder, but isn't there something like `city.In(listOfCities)`? – phipsgabler Jun 19 '12 at 20:14
  • Thanks for the response. LINQ to WCF Data Services does not support set-based queries. I found an alternative to my approach that implements an extension method [IsIn](http://blogs.msdn.com/b/phaniraj/archive/2008/07/17/set-based-operations-in-ado-net-data-services.aspx). This provides comparable functionality to the PredicateBuilder that I'm using to create dynamic LINQ queries. However, this also creates a binary expression tree which, when converted to the OData query is as recursive. – DazWilkin Jun 21 '12 at 17:32
  • If you know the exact recursion limit R, you could split up the query into sub-queries of recursion depth < R, execute each (in parallel or somehow optimized?) and combine the returned `bool`s with `||` in c#. The funny thing is that, if the number of cities isn't _really_ huge, you could implement the splitting procedure using recursion. – phipsgabler Jun 21 '12 at 18:02
  • Theoretically, the number of cities for a given state could be very large. Because of the way the expression tree is collapsed, the recursion depth is currently ~n+1 where n is the number of cities so subquerying by recursive depth won't help me. The problem I'm trying to avoid is that I could generate the OData string directly and this would solve my problem. However, it seems very inelegant and doesn't permit me to automatically leverage improvements to WCF Data Services. I think it's what I may have to do though :-( – DazWilkin Jun 21 '12 at 20:12
  • In case you are interested, I had a similar problem where the nesting would always go over the limit wth the IsIn. However, I updated to the latest WCF Data Services version (available through NuGet now) and that seemed to automatically optimize the A or B or C or D scenario. – Pablo Romeo Jun 02 '13 at 21:50

0 Answers0