Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
запрос — это выражение, которое извлекает данные из источника данных. Запросы выражаются на выделенном языке запросов. Со временем различные языки были разработаны для различных типов источников данных, например SQL для реляционных баз данных и XQuery для XML. Это позволяет разработчику приложений изучать новый язык запросов для каждого типа источника данных или формата данных, который поддерживается.
Language-Integrated запрос (LINQ) упрощает ситуацию, предлагая универсальную модель работы с данными в разных источниках данных и форматах. Всегда, выполняя запросы LINQ, вы работаете с объектами. Вы используете одни и те же базовые шаблоны кода для запроса и преобразования данных в XML-документах, SQL базах данных, наборах данных и сущностях ADO.NET, коллекциях .NET Framework и любом другом источнике или формате, для которого доступен провайдер 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<T> интерфейс. Это тот факт, что позволяет использовать массив в качестве источника данных для запроса LINQ. Типы, поддерживающие IEnumerable<T> или производный интерфейс, такой как универсальный IQueryable<T>, называются типами для запросов .
В качестве неявно запрашиваемого типа массив не требует изменения или специального лечения, чтобы служить источником данных LINQ. То же самое верно для любого типа коллекции, который поддерживает IEnumerable<T>, включая обобщенные List<T>, Dictionary<TKey,TValue> и другие классы в библиотеке классов .NET Framework.
Если исходные данные еще не реализированы IEnumerable<T>, необходим поставщик LINQ для реализации функциональности стандартных операторов запросов для данного источника данных. Например, 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. Вы пишете запросы к объектам, а во время выполнения 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 (Language-Integrated Query)).) Базовое правило просто: источник данных LINQ — это любой объект, поддерживающий универсальный IEnumerable<T> интерфейс, или интерфейс, наследуемый от него.
Замечание
Такие типы, как ArrayList, которые поддерживают неуниверсальный интерфейс IEnumerable, также могут использоваться в качестве источников данных LINQ. Чтобы увидеть пример использования ArrayList, см. статью "Практическое руководство: запрос 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
в предыдущем примере, должна быть запрашиваемым типом. Тип 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
запроса содержит определение запроса, а не результаты запроса, вы можете выполнять его так часто, как потребуется, используя переменную 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 метод.