Написание первого запроса LINQ (Visual Basic)
Запрос представляет собой выражение, извлекающее данные из источника данных. Запросы выражаются на выделенном языке запросов. Со временем различные языки были разработаны для различных типов источников данных, например SQL для реляционных баз данных и XQuery для XML. Это позволяет разработчику приложений изучать новый язык запросов для каждого типа источника данных или формата данных, который поддерживается.
Языковой интегрированный запрос (LINQ) упрощает ситуацию, предлагая consis режим палатки l для работы с данными в различных типах источников данных и форматов. В запросе LINQ вы всегда работаете с объектами. Вы используете те же основные шаблоны кодирования для запроса и преобразования данных в XML-документах, базах данных SQL, ADO.NET наборах данных и сущностях, платформа .NET Framework коллекциях и любом другом источнике или формате, для которого доступен поставщик LINQ. В этом документе описываются три этапа создания и использования базовых запросов LINQ.
Три этапа операции запроса
Операции запроса LINQ состоят из трех действий:
Получите источник данных или источники.
создание запроса;
Выполните запрос.
В 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
и 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 метод.