Поделиться через


Интегрированный язык запросов (LINQ)

Language-Integrated Query (LINQ) — это название набора технологий, основанных на интеграции возможностей выполнения запросов непосредственно в язык C#. Традиционно запросы к данным выражаются как простые строки без проверки типа во время компиляции или поддержки IntelliSense. Кроме того, необходимо узнать другой язык запросов для каждого типа источника данных: базы данных SQL, XML-документы, различные веб-службы и т. д. При использовании LINQ запрос — это конструкция языка первого класса, как классы, методы и события.

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

В следующем примере показана полная операция запроса. Полная операция включает создание источника данных, определение выражения запроса и выполнение запроса в инструкции foreach .

// Specify the data source.
int[] scores = [97, 92, 81, 60];

// Define the query expression.
IEnumerable<int> scoreQuery =
    from score in scores
    where score > 80
    select score;

// Execute the query.
foreach (var i in scoreQuery)
{
    Console.Write(i + " ");
}

// Output: 97 92 81

Возможно, потребуется добавить директиву using , using System.Linq;чтобы выполнить компиляцию в предыдущем примере. Последние версии .NET используют неявные использование для добавления этой директивы в качестве глобального использования. Для более старых версий необходимо добавить его в исходный код.

Обзор выражения запроса

  • Выражения запросов запрашивают и преобразуют данные из любого источника данных с поддержкой LINQ. Например, один запрос может извлекать данные из базы данных SQL и создавать XML-поток в виде выходных данных.
  • Выражения запросов используют множество знакомых конструкций языка C#, что упрощает их чтение.
  • Переменные в выражении запроса являются строго типизированными.
  • Запрос не выполняется, пока не производится итерирование по переменной запроса, например в операторе foreach.
  • Во время компиляции выражения запросов преобразуются в стандартные вызовы метода оператора запроса в соответствии с правилами, определенными в спецификации C#. Любой запрос, который можно выразить с помощью синтаксиса запроса, также можно выразить с помощью синтаксиса метода. В некоторых случаях синтаксис запросов является более читаемым и кратким. В других случае синтаксис метода является более читаемым. Между двумя различными формами нет никакой разницы в семантике или производительности. Дополнительные сведения см. в спецификации языка C# и обзоре стандартных операторов запросов.
  • Некоторые операции запроса, такие как Count или Max, не имеют эквивалентного предложения выражения запроса и поэтому должны быть выражены как вызов метода. Синтаксис метода можно сочетать с синтаксисом запросов различными способами.
  • Выражения запросов можно компилировать в деревья выражений или делегаты в зависимости от типа данных, к которому применяется запрос. IEnumerable<T> запросы компилируются делегатам. IQueryable и IQueryable<T> запросы компилируются в деревья выражений. Дополнительные сведения см. в деревах выражений.

Как включить запросы LINQ к вашему источнику данных

Данные в памяти

Существует два способа включения запросов LINQ к данным в памяти. Если данные являются типом, реализующим IEnumerable<T>, запрашиваете данные с помощью LINQ to Objects. Если реализация IEnumerable<T> интерфейса для включения перечисления не имеет смысла, вы определяете стандартные методы оператора запроса LINQ либо в этом типе, либо в виде методов расширения для данного типа. Пользовательские реализации стандартных операторов запросов должны использовать отложенное выполнение для возврата результатов.

Удаленные данные

Лучший вариант включения запросов LINQ к удаленному источнику данных — реализовать IQueryable<T> интерфейс.

Поставщики IQueryable LINQ

Поставщики LINQ, которые реализуют IQueryable<T> , могут значительно отличаться в их сложности.

Менее сложный IQueryable поставщик может получить доступ к одному методу из веб-службы. Этот тип поставщика очень конкретный, так как он ожидает конкретных сведений в запросах, которые он обрабатывает. Он имеет систему закрытого типа, возможно, предоставляя один тип результата. Большая часть выполнения запроса происходит локально, например с помощью Enumerable реализаций стандартных операторов запросов. Менее сложный поставщик может изучить только одно выражение вызова метода в дереве выражений, представляющее запрос, и позволить оставшейся логике запроса обрабатываться в другом месте.

Поставщик IQueryable средней сложности может использовать источник данных с частично экспрессивным языком запросов. Если он предназначен для веб-службы, он может получить доступ к нескольким методам веб-службы и выбрать, какой метод вызвать, на основе информации, которую ищет запрос. Поставщик средней сложности будет иметь более богатую систему типов, чем простой поставщик, но она по-прежнему будет фиксированной системой типов. Например, поставщик может предоставлять типы, имеющие связи "один ко многим", которые можно обойти, но не предоставляют технологии сопоставления для определяемых пользователем типов.

Сложный IQueryable поставщик, такой как поставщик Entity Framework Core , может перевести полные запросы LINQ на язык экспрессивных запросов, например SQL. Сложный поставщик является более общим, так как он может обрабатывать более широкий спектр вопросов в запросе. Он также имеет систему открытого типа и поэтому должен содержать обширную инфраструктуру для сопоставления определяемых пользователем типов. Для разработки сложного поставщика требуется значительное количество усилий.