Написание первого запроса LINQ (Visual Basic)
Запрос представляет собой выражение, извлекающее данные из источника данных. Запросы выражаются на выделенном языке запросов. Со временем были разработаны различные языки для различных типов источников данных, например SQL для реляционных баз данных и XQuery для XML. Поэтому разработчики приложений должны изучать новый язык запросов для каждого поддерживаемого типа источника данных или формата данных.
LINQ упрощает ситуацию, предлагая согласованную модель для работы с данными в различных видах источников и форматов данных. В запросе LINQ работа всегда осуществляется с объектами. Для запросов и преобразования данных в XML-документах, базах данных SQL, наборах данных и сущностях ADO.NET, коллекциях .NET Framework и любых других источников или форматов, для которых доступен поставщик LINQ, используются одинаковые базовые шаблоны кодирования. В этом документе описываются три фазы создания и использования основных запросов LINQ.
Для просмотра связанных демонстрационных видеороликов перейдите по ссылке Инструкции. Введение в LINQ.
Три этапа операции запроса
Операции запросов LINQ состоят из трех действий.
Получение источника или источников данных.
Создание запроса.
Выполнение запроса.
В LINQ выполнение запроса отличается от создания запроса. Простое создание запроса не связано с возвращением данных. Эта особенность обсуждается более подробно далее в этом разделе.
В следующем примере показаны три части операции запроса. В примере используется массив целых чисел в качестве удобного источника данных для демонстрационных целей. Однако те же принципы применимы и к другим источникам данных.
Примечание
На Страница "Компиляция" в конструкторе проектов (Visual Basic), убедитесь, что Option infer имеет значение На.
' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}
' Query creation.
Dim evensQuery = From num In numbers
Where num Mod 2 = 0
Select num
' Query execution.
For Each number In evensQuery
Console.Write(number & " ")
Next
Результат
0 2 4 6
Источник данных
В предыдущем примере источником данных является массив, поэтому он неявно поддерживает универсальный интерфейс IEnumerable. Именно этот факт позволяет использовать массив в качестве источника данных для запроса LINQ. Типы, которые поддерживают IEnumerable или производный интерфейс как универсальный шаблон IQueryable вызываются запрашиваемыми типами.
Являясь неявно запрашиваемым типом, массив не требует изменений или специальной обработки, чтобы служить источником данных LINQ. То же самое верно для любого типа коллекции, поддерживает IEnumerable, включая универсальные List, Dictionary и других классов в библиотеке классов .NET Framework.
Если источник данных еще не реализует IEnumerable, необходим поставщик LINQ для реализации функциональности стандартных операторов запросов для источника данных. Например, LINQ to XML выполняет работу по загрузке XML-документа в запрашиваемый тип XElement, как показано в следующем примере. Дополнительные сведения о стандартных операторах запроса см в разделе Общие сведения о стандартных операторах запроса.
' Create a data source from an XML document.
Dim contacts = XElement.Load("c:\myContactList.xml")
Используя LINQ to SQL, сначала создайте объектно-реляционное сопоставление в режиме разработки вручную либо с помощью Реляционный конструктор объектов. Напишите запросы к объектам, а во время выполнения LINQ to SQL будет осуществлять взаимодействие с базой данных. В следующем примере customers представляет определенную таблицу в базе данных, а Table поддерживает универсальный IQueryable.
' Create a data source from a SQL table.
Dim db As New DataContext("C:\Northwind\Northwnd.mdf")
Dim customers As Table(Of Customer) = db.GetTable(Of Customer)
Для получения дополнительных сведений о способах создания определенных типов источников данных см. документацию по различным поставщикам LINQ. (Список этих поставщиков содержится в разделе LINQ.) Основное правило является простым: источник данных LINQ — это любой объект, поддерживающий универсальный интерфейс IEnumerable или интерфейс, наследуемый от него.
Примечание
Такие типы, как ArrayList, поддерживающие неуниверсальный интерфейс IEnumerable, также могут использоваться в качестве источников данных LINQ.Пример, использующий ArrayList см. в разделе Практическое руководство. Выполнение запроса к ArrayList с помощью LINQ.
Запрос
В запросе указывается, какие сведения требуется извлечь из источника или источников данных. Также можно указать способ сортировки, группировки или структурирования сведений до их возвращения. Для создания запросов в язык Visual Basic включен новый синтаксис запроса.
В следующем примере запрос возвращает все четные числа из массива целых чисел numbers.
' Data source.
Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6}
' Query creation.
Dim evensQuery = From num In numbers
Where num Mod 2 = 0
Select num
' Query execution.
For Each number In evensQuery
Console.Write(number & " ")
Next
Выражение запроса содержит три предложения: From, Where и Select. Конкретная функциональность и назначение каждого предложения выражения запроса рассматривается в разделе Основные операции запроса (Visual Basic). Дополнительные сведения см. в разделе Запросы (Visual Basic). Обратите внимание, что в LINQ определение запроса часто хранится в переменной и выполняется позднее. Переменная запроса, например evensQuery в предыдущем примере, должна быть запрашиваемым типом. Тип evensQueryIEnumerable(Of Integer), присвоенного компилятором, используя вывод локального типа.
Важно помнить, что сама переменная запроса не выполняет действий и не возвращает никаких данных. Она только хранит определение запроса. В предыдущем примере запрос выполняется циклом For Each.
Выполнение запроса
Выполнение запроса не зависит от его создания. Создание запроса определяет запрос, но выполнение инициируется другим механизмом. Запрос может выполняться по мере его определения (немедленное выполнение), или его определение может быть сохранено и запрос может быть выполнен позднее (отложенное выполнение).
Отложенное выполнение
Обычный запрос LINQ напоминает запрос в предыдущем примере, в котором определен evensQuery. Запрос создается, но выполняется не сразу. Определение запроса хранится в переменной запроса evensQuery. Запрос выполняется позже, обычно с помощью цикла For Each, который возвращает последовательность значений, или при помощи стандартного оператора запроса, такого как Count или Max. Такой процесс называется отложенным выполнением.
' Query execution that results in a sequence of values.
For Each number In evensQuery
Console.Write(number & " ")
Next
' Query execution that results in a single value.
Dim evens = evensQuery.Count()
Доступ к извлеченной последовательности значений осуществляется с помощью переменной итерации в цикле For Each (number в предыдущем примере). Поскольку переменная запроса evensQuery содержит определение, а не результаты запроса, запрос можно выполнять так часто, как требуется. Например, приложение может работать с базой данных, которая непрерывно обновляется отдельным приложением. После создания запроса, извлекающего данные из базы данных, можно использовать цикл For Each, чтобы выполнить запрос повторно, извлекая каждый раз последние данные.
В следующем примере демонстрируется отложенное выполнение. После того, как evensQuery2 определен и выполнен с помощью цикла For Each, как в предыдущих примерах, некоторые элементы в источнике данных numbers изменяются. Затем второй цикл For Each еще раз выполняет evensQuery2. Результаты, извлеченные во второй раз, отличаются от изначальных, поскольку цикл For Each снова выполняет запрос, используя новые значения в numbers.
Dim numberArray() = {0, 1, 2, 3, 4, 5, 6}
Dim evensQuery2 = From num In numberArray
Where num Mod 2 = 0
Select num
Console.WriteLine("Evens in original array:")
For Each number In evensQuery2
Console.Write(" " & number)
Next
Console.WriteLine()
' Change a few array elements.
numberArray(1) = 10
numberArray(4) = 22
numberArray(6) = 8
' Run the same query again.
Console.WriteLine(vbCrLf & "Evens in changed array:")
For Each number In evensQuery2
Console.Write(" " & number)
Next
Console.WriteLine()
Результат
Evens in original array:
0 2 4 6
Evens in changed array:
0 10 2 22 8
Немедленное выполнение
При отложенном выполнении запросов определение запроса хранится в переменной запроса для последующего выполнения. При немедленном выполнении запрос выполняется во время своего определения. Выполнение инициируется при применении метода, которому необходим доступ к отдельным элементам результата запроса. Немедленное выполнение часто производится принудительно с помощью одного из стандартных операторов запроса, возвращающего одно значение. Примерами являются Count, Max, Average и First. Эти стандартные операторы запроса выполняют запрос при осуществлении вычислений и возвращают единственное значение. Дополнительные сведения о стандартных операторах запроса, возвращающих одно значение, содержатся в разделах Операции статистической обработки, Операции с элементами и Операции квантификаторов.
Следующий запрос возвращает количество четных чисел в массиве целых чисел. Определение запроса не сохраняется, а numEvens является простым Integer.
Dim numEvens = (From num In numbers
Where num Mod 2 = 0
Select num).Count()
Того же результата можно добиться с помощью метода Aggregate.
Dim numEvensAgg = Aggregate num In numbers
Where num Mod 2 = 0
Select num
Into Count()
Можно также принудительно выполнить запрос путем вызова метода ToList или ToArray в запросе (немедленный) или переменной запроса (отложенный), как показано в следующем коде.
' Immediate execution.
Dim evensList = (From num In numbers
Where num Mod 2 = 0
Select num).ToList()
' Deferred execution.
Dim evensQuery3 = From num In numbers
Where num Mod 2 = 0
Select num
' . . .
Dim evensArray = evensQuery3.ToArray()
В предыдущих примерах evensQuery3 является переменной запроса, evensList является списком, а evensArray является массивом.
Использование ToList или ToArray для принудительного немедленного выполнения полезно в тех сценариях, в которых требуется выполнить запрос немедленно и кэшировать результаты в одном объекте коллекции. Дополнительные сведения об этих методах см. в разделе Преобразование типов данных.
Выполнение запроса можно вызвать с помощью метода IEnumerable, например System#Collections#IEnumerable#GetEnumerator.
Связанные демонстрационные видеоролики
How Do I: Get Started with LINQ?
Video How to: Writing Queries in Visual Basic
См. также
Задачи
Основные понятия
Общие сведения о реляционном конструкторе объектов
Вывод локального типа (Visual Basic)
Общие сведения о стандартных операторах запроса
Знакомство с LINQ в Visual Basic