Написание первого запроса LINQ (Visual Basic)

Запрос представляет собой выражение, извлекающее данные из источника данных. Запросы выражаются на выделенном языке запросов. Со временем были разработаны различные языки для различных типов источников данных, например SQL для реляционных баз данных и XQuery для XML. Поэтому разработчики приложений должны изучать новый язык запросов для каждого поддерживаемого типа источника данных или формата данных.

LINQ (Language-Integrated Query) упрощает ситуацию, предлагая согласованную модель для работы с данными в различных видах источников и форматов данных. В запросе LINQ работа всегда осуществляется с объектами. Для запросов и преобразования данных в XML-документах, базах данных SQL, наборах данных и сущностях ADO.NET, коллекциях .NET Framework и любых других источников или форматов, для которых доступен поставщик LINQ, используются одинаковые базовые шаблоны кодирования. В этом документе описываются три фазы создания и использования основных запросов LINQ.

ссылка на видео Для просмотра связанных демонстрационных видеороликов перейдите по ссылке Инструкции. Введение в LINQ.

Три этапа операции запроса

Операции запросов LINQ состоят из трех действий.

  1. Получение источника или источников данных.

  2. Создание запроса.

  3. Выполнение запроса.

В LINQ выполнение запроса отличается от создания запроса. Простое создание запроса не связано с возвращением данных. Эта особенность обсуждается более подробно далее в этом разделе.

В следующем примере показаны три части операции запроса. В примере используется массив целых чисел в качестве удобного источника данных для демонстрационных целей. Однако те же принципы применимы и к другим источникам данных.

' 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<T>. Именно этот факт позволяет использовать массив в качестве источника данных для запроса LINQ. Типы, поддерживающие IEnumerable(Of T) или производные интерфейсы, такие как универсальный IQueryable<T>, называются запрашиваемыми типами.

Являясь неявно запрашиваемым типом, массив не требует изменений или специальной обработки, чтобы служить источником данных LINQ. Это справедливо и для любого типа коллекции, который поддерживает интерфейс IEnumerable(Of T), включая универсальные классы List<T>, Dictionary<TKey, TValue> и другие классы в библиотеке классов .NET Framework.

Если источник данных еще не реализует IEnumerable(Of T), необходим поставщик 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<TEntity> поддерживает универсальный IQueryable<T>.

' 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<T> или интерфейс, наследуемый от него.

Примечание

Такие типы, как 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 в предыдущем примере, должна иметь запрашиваемый тип. Типом evensQuery является IEnumerable(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, например IEnumerable.GetEnumerator.

Связанные демонстрационные видеоролики

How Do I: Get Started with LINQ?

Video How to: Writing Queries in Visual Basic

См. также

Задачи

Примеры LINQ

Основные понятия

Общие сведения о реляционном конструкторе объектов

Вывод локального типа (Visual Basic)

Общие сведения о стандартных операторах запроса

Знакомство с LINQ в Visual Basic

Другие ресурсы

Приступая к работе с LINQ в Visual Basic

LINQ в Visual Basic

Запросы (Visual Basic)

Журнал изменений

Дата

Журнал

Причина

Март 2011

Изменен последний пример.

Обратная связь от клиента.