Стандартные операторы запроса с LINQ - Преобразования и кванторы
ОГЛАВЛЕНИЕ
Преобразования и кванторы
Если нужно определить, присутствует ли то или иное значение в последовательности, можно использовать стандартный оператор Any. Кванторы (Any, All, Contains) позволяют просмотреть последовательность элементов и определить, соответствует она условиям лямбда-выражения или нет. Их удобно использовать, если, к примеру, нужно определить, существует ли клиент, проживающий по указанному адресу, в одной стране живут клиенты или нет, и так далее.
Запрос LINQ, приведенный ниже, позволяет проверить, все ли британские подданные из числа клиентов компании живут в Лондоне. Здесь используется квантор All и лямбда-выражение, определяющее, указан Лондон в качестве города проживания или нет. Если все элементы последовательности соответствуют этому критерию, то оператор All возвращает значение true:
using (Entities entities = new Entities())
{
bool allUKCustomerAreFromLondon = (from c in entities.Customers
where c.Country == "UK"
select c).All(
c => c.City.Equals("London"));
Console.WriteLine(allUKCustomerAreFromLondon ? "Yes" : "No");
}
Еще один пример: есть ли среди британских клиентов компании люди, живущие в городе Каус. В этом случае используется оператор Any:
using (Entities entities = new Entities())
{
bool isOneUKCustomerFromCowes = (from c in entities.Customers
where c.Country == "UK"
select c).Any(
c => c.City.Equals("Cowes"));
Console.WriteLine(isOneUKCustomerFromCowes? "Yes" : "No");
}
Оператор Contains по принципу действия схож с оператором Any: он тоже позволяет определить, есть ли в последовательности указанный элемент. Разница в том, что оператор Any определяет, присутствует ли определенное значение в элементе последовательности, а оператор Contains — присутствует ли в последовательности экземпляр элемента. Например, прежде чем добавить объект в последовательность, можно проверить, нет ли его там уже. На рис. 2, показано, как это сделать.
Figure 2 Using Contains and Conversion
using (Entities entities = new Entities())
{
Customers customerBSBEV = (from c in entities.Customers
where c.CustomerID == "BSBEV"
select c).First();
var customersUK = from c in entities.Customers
where c.Country == "UK"
select c;
bool isCustomerInSequence = customersUK.Contains(customerBSBEV);
Console.WriteLine(isCustomerInSequence? "Yes" : "No");
}
Обратите внимание, что в этом примере сущность Customers мы получаем для клиента BSBEV. Затем мы получаем последовательность сущностей Customer, соответствующих клиентам, проживающим в Великобритании. И наконец, оператор Contains проверяет, есть ли в последовательности экземпляр, присвоенный в качестве значения переменной customerBSBEV.
Вариант использования оператора Contains, показанный на рис. 2, применим тогда, когда наверняка известно, что объекты можно будет сравнить на основании экземпляров. А что если проверку нужно провести на основании логической идентификации? Оператор Contains позволяет передать объект, реализуя интерфейс IEqualityComparer<T>. Если оператор Contains должен работать на основании идентификатора клиента, код, приведенный на рис. 2, можно переписать следующим образом:
using (Entities entities = new Entities())
{
...
bool isCustomerInSequence = customersUK.Contains(customerBSBEV,
new CustomerComparer());
Console.WriteLine(isCustomerInSequence? "Yes" : "No");
}
Элемент CustomerComparer определяется так:
private class CustomerComparer : IEqualityComparer<Customers>
{
public bool Equals(Customers x, Customers y) {
if (x == null || y == null)
return false;
return x.CustomerID.Equals(y.CustomerID);
}
...
}
Выводы
Существует множество стандартных операторов, используемых в качестве методов расширения классов последовательностей Enumerable и Queryable. Они позволяют расширить возможности LINQ. Мы наглядно продемонстрировали, насколько большое количество средств, появившихся в платформе .NET Framework 3.5 (в их числе лямбда-выражения, LINQ, Entity Framework, неявно типизированные переменные), помогает повысить надежность кода и упростить логику приложения.
Джон Папа (John Papa) — старший консультант по технологии .NET в компании ASPSOFT (aspsoft.com) и страстный поклонник бейсбола, который почти все летние вечера проводит, болея за «Янки» со своим семейством и верным псом Кади. Джон, имея звание MVP по C#, является автором нескольких книг технологиям доступа к данным. Он также является спикерм INETA.