The function iterates over a collection of items and builds a predicate by adding an or
condition for each ClientId
property value.
In the early versions of Linq2SQL there was no support for method Contains
so you weren't able to perform a query like this:
IEnumerable<Purchase> purchases = LoadSelectedItems();
var clientIds = purchases.Select( p => p.ClientId ).ToArray();
var results = db.Clients.Where( c => clientIds.Contains( c.Id )); // Did not work.
The workaround for this problem is to create a predicate that would check using or
whether an Id
would match a specific value. So, for the above example, if clientIds = {1, 2, 3}
the Where
clause would be written as:
var results = db.Clients.Where( c => c.Id == 1 || c.Id == 2 || c.Id == 3);
As you can see, this kind of statement is not very elegant, becomes unreadable when the collection of values to check against (i. e. clientIds
) is very large and, most important, you cannot know a priori what the values will be to hardcode them.
So, to overcome this problem, the solution is to generalize the above predicate with a variable collection of values. And this is done simply with the following algorithm:
- Create an
Expression
that returns false
; if we return true
the compiler will short-circuit the evaluation (because we're using or
) and will return true for all the items;
- For each item in the collection of values add an
or
clause with the value of the item.
Now, your example can be converted to a foreach this way:
// start with a predicate returning false
// this is the seed of the Aggregate method
Expression<Func<Purchase, bool>> predicate = m => false;
// Now, iterate the collection and build the full predicate
foreach( var id in idList)
{
// Build the predicate by invoking a function which returns the client id of the
// purchase and comparing it with the value of the current id from the idList
predicate = predicate.Or(item => item.ClientId == id);
}
Hope this helps.