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

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

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

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

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

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

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

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

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

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

Примечание.

На странице компиляции конструктор проектов (Visual Basic) убедитесь, что параметр имеет значение On.

' 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<T> или производный интерфейс, например универсальный интерфейс IQueryable<T>, называются запрашиваемыми типами.

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

Если исходные данные еще не реализуются, поставщик LINQ необходим для реализации IEnumerable<T>функциональных возможностей стандартных операторов запросов для этого источника данных. Например, LINQ to XML обрабатывает работу загрузки XML-документа в запрашиваемый XElement тип, как показано в следующем примере. Дополнительные сведения о стандартных операторах запросов см. в обзоре стандартных операторов запросов (Visual Basic).

' Create a data source from an XML document.
Dim contacts = XElement.Load("c:\myContactList.xml")

При использовании LINQ to SQL сначала создается сопоставление реляционных объектов во время разработки вручную или с помощью средств LINQ to SQL в Visual Studio в Visual Studio . Запросы к объектам записываются, а во время выполнения 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см. в статье "Практическое руководство. Запрос массива" с помощью LINQ (Visual Basic).

Запрос

В запросе вы указываете, какие сведения необходимо получить из источника данных или источников. Кроме того, вы можете указать способ сортировки, группировки или структурирования этих сведений перед возвратом. Чтобы включить создание запросов, 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). Дополнительные сведения см. в статье Запросы. Обратите внимание, что в LINQ определение запроса часто хранится в переменной и выполняется позже. Переменная запроса, например evensQuery в предыдущем примере, должна быть запрашиваемым типом. Тип , IEnumerable(Of Integer)назначенный evensQuery компилятором с помощью вывода локального типа.

Важно помнить, что переменная запроса не принимает никаких действий и не возвращает данные. Он сохраняет только определение запроса. В предыдущем примере это 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 данных. Затем снова запускается evensQuery2 второй For Each цикл. Результаты отличаются во второй раз, так как 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и AverageFirst. Эти стандартные операторы запросов выполняют запрос, как только они применяются, чтобы вычислить и вернуть одноэлементный результат. Дополнительные сведения о стандартных операторах запросов, возвращающих отдельные значения, см. в разделе "Операции агрегирования", "Операции элемента" и "Квантификатор".

Следующий запрос возвращает количество четных чисел в массиве целых чисел. Определение запроса не сохраняется и 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 метод.

См. также