Часто задаваемые вопросы о LINQ: третья часть - Что такое компилируемые запросы?

ОГЛАВЛЕНИЕ

Что такое компилируемые запросы?

LINQ предоставляет нечто под названием «компилируемые запросы LINQ». В компилируемых запросах LINQ схема кэшируется в статическом классе. Статический класс является глобальным кэшем. LINQ использует схему запроса из объекта статического класса, а не строит и готовит схему запроса с нуля.

Рисунок: Кэширование запроса LINQ

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

Рисунок: Схема запроса обходит много шагов

Какие разные шаги связаны с написанием компилируемых запросов LINQ?

Первый – импортировать пространство имен Data.Linq.

Import namespace
using System.Data.Linq;

Синтаксис для написания компилируемых запросов немного загадочный. Поэтому надо разбить этот синтаксис на маленькие кусочки и постараться увидеть, как выглядит полный синтаксис. Чтобы выполнить компилируемую функцию, пишется функция для указателя. Эта функция должна быть статической, чтобы механизм LINQ мог использовать схему запроса, хранящуюся в объектах статического класса. Функция определяется следующим образом. Она начинается с public static, указывающего, что эта функция статическая. Затем используется ключевое слово Func для определения входных параметров и выходных параметров. Последовательность параметров определяется так:
•    Первый параметр должен быть контекстом данных. Тип данных определяется как DataContext.
•    За ним идет один или больше входных параметров; сейчас есть только один, т. е. код клиента, поэтому тип данных второго параметра определен как string.
•    Покончив со всеми входными параметрами, надо определить тип данных выходных. Сейчас выходной тип данных определен как IQueryable.

Эта функция делегата называется getCustomers.

public static Func<DataContext, string, IQueryable<clsCustomerEntity>> getCustomers

Надо вызвать метод Compiled статического класса CompiledQuery с объектом DataContext и требуемыми определенными входными параметрами с последующим запросом LINQ. В следующем фрагменте не был указан запрос LINQ для минимизации сложностей:

CompiledQuery.Compile((DataContext db, string strCustCode)=> Your LINQ Query );

Два вышеприведенных фрагмента кода объединяются. Ниже показан полный фрагмент кода:

public static Func<DataContext, string, IQueryable<clsCustomerEntity>> 
  getCustomers= CompiledQuery.Compile((DataContext db, string strCustCode)=> Your LINQ Query );

Надо обернуть эту статическую функцию в статический класс. Вышеопределенная функция обертывается в статический класс clsCompiledQuery.

public static class clsCompiledQuery
{
    public static Func<DataContext, string, IQueryable<clsCustomerEntity>>
    getCustomers = CompiledQuery.Compile((DataContext db, string strCustCode)
    => from objCustomer in db.GetTable<clsCustomerEntity>()
    where objCustomer.CustomerCode == strCustCode
    select objCustomer);
}

Использовать компилируемый запрос просто – вызывается статическая функция. Сейчас эта функция возвращает тип данных IEnumerable. Поэтому надо определить сущность клиента IEnumerable, которая будет действовать через функцию делегата getCustomers. Сущность клиента обходится в цикле с помощью класса clsCustomerEntity.

IQueryable<clsCustomerEntity> objCustomers = 
             clsCompiledQuery.getCustomers(objContext, txtCustomerCode.Text);
foreach (clsCustomerEntity objCustomer in objCustomers)
{
    Response.Write(objCustomer.CustomerName + "<br>");
}

Что такое подтверждения внутри памяти и физические подтверждения LINQ?

Объекты-сущности образуют основу технологий LINQ. Данные, отправленные в базу данных, проходят через объекты LINQ. Операции над базой данных выполняются посредством класса DataContext. Как сказано ранее, сущности образуют основу LINQ, поэтому все данные сначала отправляются этим сущностям и затем направляются в фактическую физическую базу данных. Из-за таких особенностей работы подтверждение базы данных является двушаговым процессом: первый шаг - подтверждение внутри памяти, а затем физическое подтверждение. Для выполнения операций внутри памяти DataContext предоставляет методы DeleteOnSubmit и InsertOnSubmit. При вызове этих методов из класса DataContext они добавляют и обновляют данные в памяти объекта-сущности. Эти методы не меняют и не добавляют новых данных в фактическую базу данных. После завершения операций внутри памяти для отправки всех обновлений в базу данных вызывается метод SubmitChanges(). Он, наконец, помещает данные в физическую базу данных.

Рассматривается таблица клиента (customerid, customercode и customername) и показывается, как делаются операции подтверждения внутри памяти и физического подтверждения.