Часто задаваемые вопросы о 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) и показывается, как делаются операции подтверждения внутри памяти и физического подтверждения.