функция перебирает коллекции элементов и создает предикат, добавив or
для каждого значения ClientId
.
В ранних версиях Linq2SQL не было никакой поддержки для метода Contains
так что вы не были в состоянии выполнить запрос следующим образом:
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.
Обойти эту проблему, чтобы создать предикат, который будет проверять используя or
, соответствует ли Id
конкретному значению. Таким образом, для приведенного выше примера, если clientIds = {1, 2, 3}
оговорка Where
будет записана как:
var results = db.Clients.Where(c => c.Id == 1 || c.Id == 2 || c.Id == 3);
Как вы можете видеть, этот вид заявления не очень элегантно, становится нечитаемым, когда совокупность значений для проверки против (т.е. clientIds
) очень большой и, самое главное, вы не можете знать априори, какие значения будут для них жестко кодировать. Итак, чтобы преодолеть эту проблему, решение состоит в том, чтобы обобщить вышеуказанный предикат с переменным набором значений. И это делается просто с помощью следующего алгоритма:
- Создать
Expression
, которая возвращает false
; если мы вернем true
, компилятор проведет короткую замыкание оценки (потому что мы используем or
) и вернем true для всех элементов;
- Для каждого элемента в коллекции значений добавьте предложение
or
со значением элемента.
Теперь, ваш пример может быть преобразован в Еогеасп таким образом:
// 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);
}
Надеется, что это помогает.
Спасибо! это действительно полезно. Любые указатели на LinQKit Expand(), пожалуйста? – Abhijeet
@Abhijeet, к сожалению, не могу сказать ... 'Expand()' метод пытается «оптимизировать» лямбда-выражение, чтобы он мог быть эффективно преобразован в SQL-запрос. – RePierre