Tyring to OR more than 10-12 single predicate descriptions for the same property one a time into a composite predicate description causes timeouts on the entity server and each time you OR a new predicate, it gets progressively slower, getting really bad as you get over 15 ORs. The last call we see (before hitting the timeout) is to IdeaBlade.Linq.CompositePredicateDescription.InstanceType.get() line 85.
I've been able to use LinqPad against our generic EF datamodels with the standard EF PredicateBuilder to do the same thing and it can handle over 400 predicates ORed together (LinqPad blows up if I try 500) so this can't be an EF limitation.
The property in this case was an INT field (but this probably happens for any type) and each predicate was just using the filter for equality. The code that creates these is very dynamic but essentially, after first creating a single predicate description, if it finds another predicate for the column, it builds a new predicate description and combines the first 2 single predicates into a composite. Subsequent predicates on that same property uses the composite to combine it with an OR on each new predicate.
In this particular case, I can't really use an InList filter operator without massive code restructuring to try and gather up all the related filter requests for a particular column as our filtering logic allows for some wildly dynamic conditions. Besides, it seems that either DevForce or EF (can't tell who) is smart enough to convert multiple ORs into a single WHERE IN clause when it generates the SQL so there isn't any performance issue at the SQL server level.
I've created an example you can use to duplicate this against NorthwindIB. Try just setting a breakpoint on "c1 = c1.Or(p);" and watch how each loop gets slower until it times out:
// test for > 20 predicates ORed together PredicateDescription p1 = null; CompositePredicateDescription c1 = null;
for (int i = 0; i <= 20; i++) { var p = new PredicateDescription(typeof (Product), "SupplierID", FilterOperator.IsEqualTo, i);
switch (i) { case 0: p1 = p; break;
case 1: c1 = p1.Or(p); p1 = null; break;
default: c1 = c1.Or(p); break; } }
|