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


Ход выполнения в технологии LINQ to Entities

Запросы к платформе Entity Framework представляются в виде дерева команд запроса, исполняемого на контексте объектов. Технология LINQ to Entities преобразует запросы Language-Integrated Queries (LINQ) в запросы в виде дерева команд, выполняет эти запросы на платформе Entity Framework и возвращает объекты, которые могут использоваться как платформой Entity Framework, так и технологией LINQ. Далее описывается процесс создания и исполнения запроса в технологии LINQ to Entities.

  1. Создайте экземпляр запроса ObjectQuery на основе объектного контекста ObjectContext.

  2. Создайте запрос по технологии LINQ to Entities на языке C# или Visual Basic с помощью экземпляра ObjectQuery.

  3. Преобразуйте выражения и стандартные операторы запросов LINQ в деревья команд.

  4. Выполните запрос в представлении дерева команд для источника данных. Все исключения, возникшие в источнике данных во время выполнения, передаются непосредственно клиенту.

  5. Верните клиенту результаты запроса.

Создание экземпляра ObjectQuery

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

Составление запроса

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

Запросы технологии LINQ to Entities можно создавать в виде двух различных синтаксических конструкций: синтаксис выражений запросов и синтаксис запросов на основе методов. Синтаксические конструкции выражения запроса и запроса на основе методов впервые появились в версиях языков C# 3.0 и Visual Basic 9.0.

Дополнительные сведения см. в разделе Запросы в LINQ to Entities.

В следующем примере используется синтаксис выражения запроса для создания экземпляра запроса ObjectQuery в контексте объекта базы данных AdventureWorks; выражение Select используется для возвращения всех строк из таблицы Product.

Using AWEntities As New AdventureWorksEntities
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productNames = _
       From p In products _
       Select p

End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productNames =
       from p in products
       select p;
}

В следующем примере используется синтаксис запроса на основе методов для создания экземпляра запроса ObjectQuery в контексте объекта базы данных AdventureWorks; выражение Select используется для возвращения всех строк из таблицы Product.

Using AWEntities As New AdventureWorksEntities


    Dim productNames = AWEntities.Product.Select(Function(p) p.Name)

End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<Product> productNames = products.Select(p => p);

}

Преобразование запросов

Для выполнения запроса в технологии LINQ to Entities на платформе Entity Framework запрос LINQ нужно преобразовать в дерево команд, которое можно выполнить на платформе Entity Framework.

Запросы в технологии LINQ to Entities состоят из стандартных операторов запросов (в частности, Select, Where и GroupBy) и выражений (x > 10, Contact.LastName и т. п.) технологии LINQ. Операторы LINQ не определяются классом, а являются методами класса. В технологии LINQ выражения могут содержать все, что допускается типами из пространства имен System.Linq.Expressions, а по расширению — все, что может быть представлено лямбда-функцией. Это надмножество выражений, допустимых для платформы Entity Framework, множество которых по определению ограничено допустимыми операциями над базой данных и поддерживается посредством ObjectQuery.

На платформе Entity Framework и операторы, и выражения представляются одной иерархией типов, которая затем помещается в дерево команд. Дерево команд используется платформой Entity Framework для выполнения запроса. Если запрос LINQ не удается выразить в виде дерева команд, при преобразовании запроса будет создано исключение. Преобразование запросов по технологии LINQ to Entities включает в себя два промежуточных преобразования: преобразование стандартных операторов запроса и преобразование выражений.

Для ряда стандартных операторов запроса LINQ не существует допустимых эквивалентов в технологии LINQ to Entities. Попытки использования этих операторов приведут к возникновению исключения в процессе перевода запроса. Список операторов, поддерживаемых технологией LINQ to Entities, см. в разделе Поддерживаемые и неподдерживаемые методы (LINQ to Entities).

Дополнительные сведения об использовании стандартных операторов запросов в технологии LINQ to Entities см. в разделе Стандартные операторы запросов в запросах LINQ to Entities.

Как правило, выражения технологии LINQ to Entities вычисляются на сервере, поэтому нельзя ожидать, что поведение выражений будет соответствовать семантике среды CLR. Дополнительные сведения см. в разделе Выражения в запросах LINQ to Entities.

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

Запрос LINQ после создания пользователем преобразуется в представление, совместимое с платформой Entity Framework (в виде деревьев команд), которое затем выполняется для источника данных. Во время выполнения запроса все выражения (или компоненты) этого запроса вычисляются на клиенте либо на сервере. Это относится и к выражениям, используемым для материализации результатов и для проекции сущностей.

Точное время выполнения выражения запроса может меняться. Запросы LINQ выполняются каждый раз при проходе по конкретной переменной запроса, а не во время создания этой переменной; такой метод называется отложенным выполнением. Можно также заставить запрос выполняться немедленно, что бывает полезно для кэширования результатов запроса. В следующем примере показано использование метода Select для выборки всех строк из таблицы Product и вывода названий продуктов. Итерация по переменной запроса в цикле foreach или For Each вызывает выполнение запроса.

Using AWEntities As New AdventureWorksEntities
    Dim products As ObjectQuery(Of Product) = AWEntities.Product

    Dim productNames = _
       From p In products _
       Select p.Name

    Console.WriteLine("Product Names:")
    For Each productName In productNames
        Console.WriteLine(productName)
    Next
End Using
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
    ObjectQuery<Product> products = AWEntities.Product;

    IQueryable<string> productNames =
       from p in products
       select p.Name;

    Console.WriteLine("Product Names:");
    foreach (var productName in productNames)
    {
        Console.WriteLine(productName);
    }
}

При выполнении запроса в технологии LINQ to Entities некоторые выражения запроса могут выполняться на сервере, а некоторые части — локально, на клиенте. Вычисление выражения на клиенте происходит до выполнения запроса на сервере. Если выражение вычисляется на клиенте, результат этого вычисления подставляется в запрос вместо выражения, после чего запрос выполняется на сервере. Поскольку запросы выполняются для источника данных, его конфигурация переопределяет правила работы, заданные на клиенте. В частности, это касается обработки значений NULL и точности числовых значений. Все исключения, возникшие на сервере во время выполнения запроса, передаются непосредственно клиенту. Дополнительные сведения см. в разделе Выполнение запроса.

Материализация

Материализацией называется процесс возвращения результатов запроса клиенту в виде типов CLR. В технологии LINQ to Entities результаты запроса никогда не возвращаются в виде записей данных. Для этого всегда используется базовый тип CLR, определяемый пользователем или платформой Entity framework либо созданный компилятором (анонимные типы). Вся материализация объектов проводится платформой Entity Framework. Все ошибки, вызванные невозможностью сопоставления между платформой Entity Framework и средой CLR, вызовут создание исключений во время материализации объекта.

Результаты запроса обычно возвращаются в одной из следующих форм.

  • Коллекция, содержащая ноль, один или несколько объектов типизированных сущностей или проекций сложных типов в модель EDM.

  • Типы CLR, поддерживаемые моделью EDM.

  • Встроенные коллекции.

  • Анонимные типы.

Дополнительные сведения см. в разделе Результаты запроса.

См. также

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

Выполнение запросов с помощью LINQ to Entities