Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Самая простая стратегия кэширования — это позволить кэшированным данным истечь после определенного периода времени. Но этот простой подход означает, что кэшированные данные не поддерживают связь со своим базовым источником данных, что приводит к устаревшим данным, хранящимся слишком долго, или к актуальным данным, срок действия которых истекает слишком рано. Лучший подход — использовать класс SqlCacheDependency, чтобы данные сохранялись в кэше, пока не были изменены базовые данные в базе данных SQL. В этом руководстве показано, как это сделать.
Введение
Методы кэширования, рассмотренные в кэшировании данных с помощью ObjectDataSource и кэширования данных в учебниках по архитектуре , использовали срок действия на основе времени для вытеснения данных из кэша после указанного периода. Этот подход является самым простым способом балансировки производительности кэширования по отношению к устаревшим данным. Выбрав срок действия x секунд, разработчик страницы признает преимущества кэширования в течение только x секунд, но может быть спокойна, что ее данные никогда не будут устаревшими не более x секунд. Конечно, для статических данных x можно расширить до времени существования веб-приложения, как было рассмотрено в руководстве по кэшированию данных при запуске приложения .
При кэшировании данных базы данных срок действия на основе времени часто выбирается для простоты использования, но часто является неадекватным решением. В идеале данные базы данных останутся в кэше до тех пор, пока исходные данные не будут изменены в базе данных; только тогда кэш будет вытеснен. Этот подход позволяет максимально повысить производительность кэширования и свести к минимуму продолжительность устаревших данных. Однако для того, чтобы воспользоваться этими преимуществами, необходимо иметь некоторую систему, которая знает, когда базовые данные базы данных были изменены и вытеснены соответствующие элементы из кэша. До ASP.NET 2.0 разработчики страниц несут ответственность за реализацию этой системы.
ASP.NET 2.0 предоставляет SqlCacheDependency
класс и необходимую инфраструктуру, чтобы определить, когда произошло изменение в базе данных, чтобы соответствующие кэшированные элементы можно было вытеснять. Существует два метода определения того, когда изменены базовые данные: уведомление и опрос. Обсудив различия между уведомлениями и опросами, мы создадим инфраструктуру, необходимую для поддержки опроса, а затем рассмотрим, как использовать SqlCacheDependency
класс в декларативных и программных сценариях.
Общие сведения о уведомлениях и опросах
Существует два метода, которые можно использовать для определения того, когда данные в базе данных были изменены: уведомление и опрос. При уведомлении база данных автоматически оповещает среду выполнения ASP.NET, когда результаты определенного запроса были изменены с момента последнего выполнения запроса, в то время как кэшированные элементы, связанные с запросом, вытесняются. При опросе сервер базы данных сохраняет сведения о времени последнего обновления определенных таблиц. Среда выполнения ASP.NET периодически опрашивает базу данных, чтобы проверить, какие таблицы изменились, так как они были введены в кэш. Таблицы, данные в которых были изменены, приводят к удалению связанных элементов кэша.
Параметр уведомления требует меньшей настройки, чем опрос и более детализирован, так как он отслеживает изменения на уровне запроса, а не на уровне таблицы. К сожалению, уведомления доступны только в полных выпусках Microsoft SQL Server 2005 (т. е. выпусков, отличных от Express). Однако параметр опроса можно использовать для всех версий Microsoft SQL Server с 7.0 по 2005 год. Так как в этих руководствах используется выпуск SQL Server 2005 Express, мы сосредоточимся на настройке и использовании параметра опроса. Ознакомьтесь с разделом "Дополнительное чтение" в конце этого руководства, чтобы получить дополнительные ресурсы в возможностях уведомлений SQL Server 2005.
При опросе база данных должна быть настроена для включения таблицы с именем AspNet_SqlCacheTablesForChangeNotification
трех столбцов — tableName
notificationCreated
и changeId
. Эта таблица содержит строку для каждой таблицы с данными, которые могут потребоваться использовать в зависимости кэша SQL в веб-приложении. Столбец tableName
указывает имя таблицы, указывая notificationCreated
дату и время добавления строки в таблицу. Столбец changeId
имеет тип int
и имеет начальное значение 0. Его значение увеличивается с каждым изменением таблицы.
AspNet_SqlCacheTablesForChangeNotification
Помимо таблицы, в базе данных также необходимо включить триггеры для каждой таблицы, которая может фигурировать в зависимости SQL-кеш. Эти триггеры выполняются всякий раз, когда строка вставляется, обновляется или удаляется, и увеличивают значение таблицы changeId
в AspNet_SqlCacheTablesForChangeNotification
.
Среда выполнения ASP.NET отслеживает текущую changeId
для таблицы при кэшировании данных с помощью SqlCacheDependency
объекта. База данных периодически проверяется и все SqlCacheDependency
объекты, которые changeId
отличаются от значения в базе данных, вытеснены, так как разное changeId
значение указывает на то, что после кэширования данных произошло изменение таблицы.
Шаг 1. Изучение программы для работы с команднойaspnet_regsql.exe
строкой
При подходе к опросу база данных должна быть настроена, чтобы содержать инфраструктуру, описанную выше: предопределенную таблицу (AspNet_SqlCacheTablesForChangeNotification
), горстку хранимых процедур и триггеры для каждой из таблиц, которые могут использоваться в зависимостях кэша SQL в веб-приложении. Эти таблицы, хранимые процедуры и триггеры можно создавать с помощью программы aspnet_regsql.exe
командной строки, которая находится в папке $WINDOWS$\Microsoft.NET\Framework\version
. Чтобы создать таблицу AspNet_SqlCacheTablesForChangeNotification
и связанные хранимые процедуры, выполните следующую команду из командной строки:
/* For SQL Server authentication... */
aspnet_regsql.exe -S server -U user -P password -d database -ed
/* For Windows Authentication... */
aspnet_regsql.exe -S server -E -d database -ed
Замечание
Для выполнения этих команд указанная учетная запись базы данных должна находиться в ролях db_securityadmin
и db_ddladmin
.
Например, чтобы добавить инфраструктуру для опроса в базу данных Microsoft SQL Server с именем pubs
на сервере базы данных с именем ScottsServer
с помощью проверки подлинности Windows, перейдите в соответствующий каталог и в командной строке введите:
aspnet_regsql.exe -S ScottsServer -E -d pubs -ed
После добавления инфраструктуры уровня базы данных необходимо добавить триггеры в эти таблицы, которые будут использоваться в зависимостях кэша SQL. Используйте программу командной aspnet_regsql.exe
строки еще раз, но укажите имя таблицы с помощью -t
параметра и вместо использования параметра -ed
используйте -et
, например:
/* For SQL Server authentication... */
aspnet_regsql.exe -S <i>server</i>
-U <i>user</i> -P <i>password</i> -d <i>database</i> -t <i>tableName</i> -et
/* For Windows Authentication... */
aspnet_regsql.exe -S <i>server</i>
-E -d <i>database</i> -t <i>tableName</i> -et
Чтобы добавить триггеры в таблицы authors
и titles
в базе данных pubs
на ScottsServer
, используйте:
aspnet_regsql.exe -S ScottsServer -E -d pubs -t authors -et
aspnet_regsql.exe -S ScottsServer -E -d pubs -t titles -et
Для этого руководства добавьте триггеры в таблицы Products
, Categories
, и Suppliers
. Мы рассмотрим конкретный синтаксис командной строки на шаге 3.
Шаг 2. Ссылка на базу данных Microsoft SQL Server 2005 Express Edition вApp_Data
В программе aspnet_regsql.exe
командной строки требуется имя базы данных и сервера, чтобы добавить необходимую инфраструктуру опроса. Но что такое база данных и имя сервера для базы данных Microsoft SQL Server 2005 Express, которая находится в папке App_Data
? Вместо того чтобы выяснять, как называются базы данных и серверы, я обнаружил, что самый простой подход заключается в подключении базы данных к экземпляру localhost\SQLExpress
и переименовании базы данных с помощью SQL Server Management Studio. Если на компьютере установлена одна из полных версий SQL Server 2005, скорее всего, на компьютере уже установлена среда SQL Server Management Studio. Если у вас есть только выпуск Express, вы можете скачать бесплатную версию Microsoft SQL Server Management Studio.
Начните с закрытия Visual Studio. Затем откройте SQL Server Management Studio и выберите подключение к localhost\SQLExpress
серверу с помощью проверки подлинности Windows.
Рис. 1. Подключение к localhost\SQLExpress
серверу
После подключения к серверу Management Studio отобразит сервер и вложенные папки для баз данных, безопасности и т. д. Щелкните правой кнопкой мыши папку "Базы данных" и выберите параметр "Подключить". Откроется диалоговое окно "Присоединение баз данных" (см. рис. 2). Нажмите кнопку "Добавить" и выберите NORTHWND.MDF
папку базы данных в папке веб-приложения App_Data
.
Рис. 2. Присоединение NORTHWND.MDF
базы данных из App_Data
папки (щелкните, чтобы просмотреть изображение полного размера)
При этом база данных будет добавлена в папку "Базы данных". Имя базы данных может быть полным путем к файлу базы данных или полный путь, заданный с помощью GUID. Чтобы избежать необходимости вводить это длинное имя базы данных при использовании средства командной строки aspnet_regsql.exe, переименуйте базу данных в более понятное для человека имя, щелкнув правой кнопкой мыши базу данных, только что подключенную и выбрав "Переименовать". Я переименовал базу данных в DataTutorials.
Рис. 3. Переименуйте присоединенную базу данных в более подходящее Human-Friendly имя
Шаг 3. Добавление инфраструктуры опроса в базу данных Northwind
Теперь, когда мы подключили NORTHWND.MDF
базу данных из App_Data
папки, мы готовы добавить инфраструктуру опроса. Если вы переименовали базу данных в DataTutorials, выполните следующие четыре команды:
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -ed
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Products -et
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Categories -et
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Suppliers -et
После выполнения этих четырех команд щелкните правой кнопкой мыши имя базы данных в Management Studio, перейдите в подменю "Задачи" и выберите "Отсоединить". Затем закройте Management Studio и снова откройте Visual Studio.
После повторного открытия Visual Studio выполните детализацию базы данных с помощью обозревателя серверов. Обратите внимание на новую таблицу (AspNet_SqlCacheTablesForChangeNotification
), новые хранимые процедуры и триггеры на таблицах Products
, Categories
и Suppliers
.
Рис. 4. База данных теперь включает необходимую инфраструктуру опроса
Шаг 4. Настройка службы опроса
После создания необходимых таблиц, триггеров и хранимых процедур в базе данных последним шагом является настройка службы опроса, которая выполняется Web.config
путем указания баз данных для использования и частоты опроса в миллисекундах. Следующая разметка опрашивает базу данных Northwind каждые секунды.
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="NORTHWNDConnectionString" connectionString=
"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NORTHWND.MDF;
Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
...
<!-- Configure the polling service used for SQL cache dependencies -->
<caching>
<sqlCacheDependency enabled="true" pollTime="1000" >
<databases>
<add name="NorthwindDB"
connectionStringName="NORTHWNDConnectionString" />
</databases>
</sqlCacheDependency>
</caching>
</system.web>
</configuration>
Значение name
в элементе <add>
(NorthwindDB) связывает имя, доступное для чтения человеком, с определенной базой данных. При работе с зависимостями кэша SQL необходимо ссылаться на имя базы данных, определенное здесь, а также таблицу, на которую основаны кэшированные данные. Мы посмотрим, как использовать SqlCacheDependency
класс для программного связывания зависимостей кэша SQL с кэшируемыми данными на шаге 6.
После того как зависимость кэша SQL будет установлена, система опроса будет подключаться к базам данных, определённым в <databases>
элементах, каждые pollTime
миллисекунд и выполнит хранимую процедуру AspNet_SqlCachePollingStoredProcedure
. Эта хранимая процедура, которая была добавлена обратно на шаге 3 с помощью средства командной строки aspnet_regsql.exe
, возвращает значения tableName
и changeId
для каждой записи в AspNet_SqlCacheTablesForChangeNotification
. Устаревшие зависимости кэша SQL вытеснены из кэша.
Этот pollTime
параметр представляет компромисс между производительностью и устаревшими данными. Небольшое pollTime
значение увеличивает количество запросов к базе данных, но быстрее вытесняет устаревшие данные из кэша. Большее значение pollTime
уменьшает количество запросов к базе данных, но увеличивает задержку между изменениями данных бэкенда и вытеснением связанных элементов кэша. К счастью, запрос базы данных выполняет простую хранимую процедуру, которая возвращает всего несколько строк из простой упрощенной таблицы. Но экспериментируйте с различными значениями pollTime
, чтобы найти идеальный баланс между доступом к базе данных и устареванием данных. Наименьшее pollTime
допустимое значение — 500.
Замечание
Приведенный выше пример предоставляет одно pollTime
значение в <sqlCacheDependency>
элементе, но при необходимости можно указать pollTime
значение в элементе <add>
. Это полезно, если у вас несколько баз данных и требуется настроить частоту опроса для каждой базы данных.
Шаг 5. Декларативная работа с зависимостями кэша SQL
В шагах 1–4 мы рассмотрели, как настроить необходимую инфраструктуру базы данных и настроить систему опроса. Благодаря этой инфраструктуре теперь можно добавить элементы в кэш данных с связанной зависимостью кэша SQL с помощью программных или декларативных методов. На этом шаге мы рассмотрим, как декларативно работать с зависимостями кэша SQL. На шаге 6 мы рассмотрим программный подход.
В руководстве по кэшированию данных с помощью ObjectDataSource рассматриваются декларативные возможности кэширования объекта ObjectDataSource. Просто установив свойство EnableCaching
на True
и свойство CacheDuration
на некоторый временной интервал, ObjectDataSource автоматически кэширует данные, возвращаемые из его базового объекта, на указанный интервал. ObjectDataSource также может использовать одну или несколько зависимостей кэша SQL.
Чтобы продемонстрировать декларативное использование зависимостей кэша SQL, откройте SqlCacheDependencies.aspx
страницу в папке Caching
и перетащите элемент GridView из панели элементов на холст конструктора. Задайте для GridView значение ID
ProductsDeclarative
и из смарт-тега выберите для привязки его к новому объекту ObjectDataSource с именем ProductsDataSourceDeclarative
.
Рис. 5. Создание объекта ObjectDataSource С именем ProductsDataSourceDeclarative
(щелкните, чтобы просмотреть изображение полного размера)
Настройте ObjectDataSource для использования класса ProductsBLL
и задайте параметр "выпадающий список" на вкладке SELECT в GetProducts()
. На вкладке UPDATE выберите перегрузку UpdateProduct
с тремя входными параметрами — productName
, unitPrice
и productID
. Задайте раскрывающимся спискам значение (Нет) на вкладках INSERT и DELETE.
Рис. 6. Используйте перегрузку UpdateProduct с тремя входными параметрами (щелкните, чтобы просмотреть изображение в полном размере)
Задайте значение (нет) для списка Drop-Down на вкладках INSERT и DELETE.
Рис. 7: Установите для вкладок INSERT и DELETE список Drop-Down в значение (нет) (щелкните, чтобы просмотреть изображение полного размера)
После завершения работы мастера настройки источника данных Visual Studio создаст BoundFields и CheckBoxFields в GridView для каждого поля данных. Удалите все поля, кроме ProductName
, CategoryName
, и UnitPrice
, и отформатируйте эти поля по вашему усмотрению. В смарт-теге GridView установите флажки "Включить разбиение по страницам", "Включить сортировку" и "Включить редактирование". Visual Studio присвоит свойству OldValuesParameterFormatString
ObjectDataSource значение original_{0}
. Чтобы функция редактирования GridView работала правильно, удалите это свойство полностью из декларативного синтаксиса или присвойте ему значение по умолчанию {0}
.
Наконец, добавьте веб-элемент управления Label над GridView и задайте значение ID
для его свойства ODSEvents
, а значение EnableViewState
для свойства False
. После внесения этих изменений декларативная разметка страницы должна выглядеть следующим образом. Обратите внимание, что я сделал ряд эстетических настроек в поля GridView, которые не необходимы для демонстрации функциональности зависимостей кэша SQL.
<asp:Label ID="ODSEvents" runat="server" EnableViewState="False" />
<asp:GridView ID="ProductsDeclarative" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSourceDeclarative"
AllowPaging="True" AllowSorting="True">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:TemplateField HeaderText="Product" SortExpression="ProductName">
<EditItemTemplate>
<asp:TextBox ID="ProductName" runat="server"
Text='<%# Bind("ProductName") %>' />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ControlToValidate="ProductName" Display="Dynamic"
ErrorMessage="You must provide a name for the product."
SetFocusOnError="True"
runat="server">*</asp:RequiredFieldValidator>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
<EditItemTemplate>
$<asp:TextBox ID="UnitPrice" runat="server" Columns="8"
Text='<%# Bind("UnitPrice", "{0:N2}") %>'></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server"
ControlToValidate="UnitPrice"
ErrorMessage="You must enter a valid currency value with
no currency symbols. Also, the value must be greater than
or equal to zero."
Operator="GreaterThanEqual" SetFocusOnError="True"
Type="Currency" Display="Dynamic"
ValueToCompare="0">*</asp:CompareValidator>
</EditItemTemplate>
<ItemStyle HorizontalAlign="Right" />
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("UnitPrice", "{0:c}") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSourceDeclarative" runat="server"
SelectMethod="GetProducts" TypeName="ProductsBLL"
UpdateMethod="UpdateProduct">
<UpdateParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
</asp:ObjectDataSource>
Затем создайте обработчик событий для события ObjectDataSource Selecting
и добавьте в него следующий код:
Protected Sub ProductsDataSourceDeclarative_Selecting _
(sender As Object, e As ObjectDataSourceSelectingEventArgs) _
Handles ProductsDataSourceDeclarative.Selecting
ODSEvents.Text = "-- Selecting event fired"
End Sub
Помните, что событие ObjectDataSource Selecting
запускается только при получении данных из базового объекта. Если ОбъектDataSource обращается к данным из собственного кэша, это событие не запускается.
Теперь посетите эту страницу через браузер. Так как мы еще не реализовали кэширование, каждый раз, когда вы переходите по страницам, сортируете или редактируете сетку, страница должна отображать текст: "Событие выбора было сработано", как показано на рисунке 8.
Рис. 8. Событие ObjectDataSource Selecting
запускается при каждом запуске GridView, редактировании или сортировке (щелкните, чтобы просмотреть изображение полного размера)
Как мы видели в учебнике по кэшированию данных с помощью ObjectDataSource, установка свойства EnableCaching
в значение True
приводит к кэшированию данных в ObjectDataSource на период, определяемый его свойством CacheDuration
. ObjectDataSource также имеет SqlCacheDependency
свойство, которое добавляет одну или несколько зависимостей SQL-кэша в данные, сохраненные в кэше, используя шаблон:
databaseName1:tableName1;databaseName2:tableName2;...
Где databaseName — это имя базы данных, как указано в name
атрибуте <add>
элемента в Web.config
, а tableName — имя таблицы базы данных. Например, чтобы создать источник данных ObjectDataSource, который кэширует данные на неопределенный срок, базирующийся на зависимости кэша SQL от таблицы NorthwindProducts
, установите для свойства ObjectDataSource EnableCaching
значение True
и его свойство SqlCacheDependency
на NorthwindDB:Products.
Замечание
Зависимость кэша SQL и истечение срока действия на основе времени можно использовать, установив на EnableCaching
, True
на временной интервал, а CacheDuration
на имя базы данных и таблицы. ObjectDataSource удалит свои данные, когда срок действия на основе времени истек, или когда система мониторинга определяет, что базовые данные базы данных изменились, в зависимости от того, что произойдёт первым.
GridView в SqlCacheDependencies.aspx
отображает данные из двух таблиц — Products
и Categories
(поле CategoryName
продукта извлекается посредством JOIN
на Categories
). Поэтому мы хотим указать две зависимости кэша SQL: NorthwindDB:Products; NorthwindDB:Categories .
Рис. 9. Настройка ObjectDataSource для поддержки кэширования с помощью зависимостей данных SQL Products
и Categories
(Нажмите, чтобы увеличить изображение)
После настройки ObjectDataSource для поддержки кэширования просмотрите страницу через браузер. Опять же, текст "Событие 'Выбор' срабатывает" должен отображаться при первом посещении страницы, но должен исчезнуть при переходе по страницам, сортировке или нажатии кнопок "Изменить" или "Отмена". Это связано с тем, что после загрузки данных в кэш ObjectDataSource он остается там, пока таблицы не будут изменены или данные не обновятся с помощью GridView.
После просмотра сетки и заметив отсутствие текста "Появляется текст о выборе события", откройте новое окно браузера и перейдите к руководству по основам в разделе "Редактирование, вставка и удаление" (~/EditInsertDelete/Basics.aspx
). Обновите имя или цену продукта. Затем в первом окне браузера просмотрите другую страницу данных, отсортируйте сетку или нажмите кнопку "Изменить строку". На этот раз событие 'Selecting event fired' должно вновь появиться, так как данные базы данных были изменены (см. рис. 10). Если текст не отображается, подождите несколько минут и повторите попытку. Помните, что служба опроса проверяет наличие изменений в Products
таблице каждые pollTime
миллисекунды, поэтому между обновлением базовых данных и при вытеснения кэшированных данных происходит задержка.
Рис. 10. Изменение таблицы продуктов вытесняет кэшированные данные продукта (щелкните, чтобы просмотреть изображение полного размера)
Шаг 6. Программная работа с классомSqlCacheDependency
Руководство Кэширование данных в архитектуре рассмотрело преимущества использования отдельного слоя кэширования в архитектуре по сравнению с тесной связкой кэширования с ObjectDataSource. В этом руководстве мы создали ProductsCL
класс для демонстрации программной работы с кэшем данных. Чтобы использовать зависимости кэша SQL в уровне кэширования, используйте SqlCacheDependency
класс.
С системой SqlCacheDependency
опроса объект должен быть связан с определенной парой базы данных и таблицы. Следующий код, например, создает SqlCacheDependency
объект на основе таблицы базы данных Products
Northwind:
Dim productsTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Products")
Два входных параметра SqlCacheDependency
конструктора — это имена базы данных и таблиц соответственно. Как и у свойства SqlCacheDependency
ObjectDataSource, используемое имя базы данных такое же, как значение, указанное в атрибуте name
элемента <add>
в Web.config
. Имя таблицы — это фактическое имя таблицы базы данных.
Чтобы связать SqlCacheDependency
с элементом, добавленным в кэш данных, используйте одну из Insert
перегрузок метода, принимающих зависимость. Следующий код добавляет значение в кэш данных на неопределенный срок, но связывает его с SqlCacheDependency
на таблице Products
. Короче говоря, значение будет оставаться в кэше до тех пор, пока не будет вытеснено из-за ограничений памяти или если система опроса обнаружит, что таблица Products
изменилась после попадания в кэш.
Dim productsTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Products")
Cache.Insert(key, _
value, _
productsTableDependency, _
System.Web.Caching.Cache.NoAbsoluteExpiration, _
System.Web.Caching.Cache.NoSlidingExpiration)
Класс слоя кэширования ProductsCL
в настоящее время кэширует данные из таблицы Products
с временем жизни 60 секунд. Давайте обновим этот класс таким образом, чтобы он использовал зависимости кэша SQL. Метод ProductsCL
класса AddCacheItem
, который отвечает за добавление данных в кэш, в настоящее время содержит следующий код:
Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
' Make sure MasterCacheKeyArray(0) is in the cache - if not, add it
If DataCache(MasterCacheKeyArray(0)) Is Nothing Then
DataCache(MasterCacheKeyArray(0)) = DateTime.Now
End If
' Add a CacheDependency
Dim dependency As _
New Caching.CacheDependency(Nothing, MasterCacheKeyArray)
DataCache.Insert(GetCacheKey(rawKey), value, dependency, _
DateTime.Now.AddSeconds(CacheDuration), _
Caching.Cache.NoSlidingExpiration)
End Sub
Обновите этот код, чтобы использовать SqlCacheDependency
объект вместо зависимости кэша MasterCacheKeyArray
:
Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
' Add the SqlCacheDependency objects for Products
Dim productsTableDependency As New _
Caching.SqlCacheDependency("NorthwindDB", "Products")
DataCache.Insert(GetCacheKey(rawKey), value, productsTableDependency, _
Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration)
End Sub
Чтобы проверить эту функциональность, добавьте GridView на страницу ниже существующего ProductsDeclarative
GridView. Установите для нового элемента GridView ID
значение ProductsProgrammatic
, и с помощью смарт-тега привяжите его к новому объекту ObjectDataSource с именем ProductsDataSourceProgrammatic
. Настройте ObjectDataSource для использования класса ProductsCL
, выбрав GetProducts
и UpdateProduct
в раскрывающихся списках на вкладках SELECT и UPDATE соответственно.
Рис. 11. Настройка ObjectDataSource для использования ProductsCL
класса (щелкните, чтобы просмотреть изображение полного размера)
Рис. 12. Выбор GetProducts
метода из списка Drop-Down вкладки SELECT (щелкните, чтобы просмотреть изображение полного размера)
Рис. 13. Выберите метод UpdateProduct из списка Drop-Down вкладки UPDATE (щелкните, чтобы просмотреть изображение полного размера)
После завершения работы мастера настройки источника данных Visual Studio создаст BoundFields и CheckBoxFields в GridView для каждого поля данных. Как и при первом добавлении GridView на эту страницу, удалите все поля, кроме ProductName
, CategoryName
и UnitPrice
, и отформатируйте эти поля по своему усмотрению. В смарт-теге GridView установите флажки "Включить разбиение по страницам", "Включить сортировку" и "Включить редактирование". Как и в ProductsDataSourceDeclarative
объекте ObjectDataSource, Visual Studio присвоит свойству ProductsDataSourceProgrammatic
ObjectDataSource OldValuesParameterFormatString
значение original_{0}
. Чтобы функция редактирования GridView работала правильно, задайте для этого свойства значение {0}
(или удалите назначение свойств из декларативного синтаксиса).
После выполнения этих задач результирующая разметка GridView и ObjectDataSource должны выглядеть следующим образом:
<asp:GridView ID="ProductsProgrammatic" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSourceProgrammatic" AllowPaging="True"
AllowSorting="True">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:TemplateField HeaderText="Product" SortExpression="ProductName">
<EditItemTemplate>
<asp:TextBox ID="ProductName" runat="server"
Text='<%# Bind("ProductName") %>' />
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
ControlToValidate="ProductName" Display="Dynamic"
ErrorMessage="You must provide a name for the product."
SetFocusOnError="True"
runat="server">*</asp:RequiredFieldValidator>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
<EditItemTemplate>
$<asp:TextBox ID="UnitPrice" runat="server" Columns="8"
Text='<%# Bind("UnitPrice", "{0:N2}") %>'></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server"
ControlToValidate="UnitPrice" Display="Dynamic"
ErrorMessage="You must enter a valid currency value with no
currency symbols. Also, the value must be greater than
or equal to zero."
Operator="GreaterThanEqual" SetFocusOnError="True"
Type="Currency" ValueToCompare="0">*</asp:CompareValidator>
</EditItemTemplate>
<ItemStyle HorizontalAlign="Right" />
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("UnitPrice", "{0:c}") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSourceProgrammatic" runat="server"
OldValuesParameterFormatString="{0}" SelectMethod="GetProducts"
TypeName="ProductsCL" UpdateMethod="UpdateProduct">
<UpdateParameters>
<asp:Parameter Name="productName" Type="String" />
<asp:Parameter Name="unitPrice" Type="Decimal" />
<asp:Parameter Name="productID" Type="Int32" />
</UpdateParameters>
</asp:ObjectDataSource>
Чтобы проверить зависимость кэша SQL в слое кэширования, установите точку останова в методе ProductCL
класса AddCacheItem
, а затем запустите отладку. При первом посещении SqlCacheDependencies.aspx
точка останова должна быть достигнута, так как данные запрашиваются в первый раз и помещаются в кэш. Затем перейдите на другую страницу в GridView или сортируйте один из столбцов. Это приводит к повторному выполнению запроса данных через GridView, но данные должны находиться в кэше, так как таблица базы данных Products
не была изменена. Если данные не найдены в кэше, убедитесь, что на компьютере достаточно памяти и повторите попытку.
После просмотра нескольких страниц в GridView откройте второе окно браузера и перейдите к учебнику "Основы" в разделе "Редактирование, вставка и удаление" (~/EditInsertDelete/Basics.aspx
). Обновите запись из таблицы Products, а затем в первом окне браузера просмотрите новую страницу или щелкните один из заголовков сортировки.
В этом сценарии вы увидите одну из двух вещей: будет достигнута точка останова, указывающая, что кэшированные данные были вытесщены из-за изменения в базе данных; или точка останова не будет достигнута, то есть SqlCacheDependencies.aspx
теперь отображает устаревшие данные. Если точка останова не достигнута, скорее всего, служба опроса еще не была запущена после изменения данных. Помните, что служба опроса проверяет наличие изменений в Products
таблице каждые pollTime
миллисекунды, поэтому между обновлением базовых данных и при вытеснения кэшированных данных происходит задержка.
Замечание
Эта задержка, скорее всего, появится при редактировании одного из продуктов через GridView в SqlCacheDependencies.aspx
. В учебном пособии Кэширование данных в архитектуре мы добавили MasterCacheKeyArray
зависимость кэша, чтобы убедиться, что данные, редактируемые с помощью метода ProductsCL
в классе UpdateProduct
, были вытеснены из кэша. Однако мы заменили эту зависимость кэша при изменении AddCacheItem
метода ранее на этом шаге, поэтому ProductsCL
класс будет продолжать отображать кэшированные данные, пока система опроса не заметит изменение таблицы Products
. Мы посмотрим, как повторно ввести зависимость кэша MasterCacheKeyArray
на шаге 7.
Шаг 7. Связывание нескольких зависимостей с кэшируемым элементом
Имейте в виду, что зависимость кэша используется для гарантии того, MasterCacheKeyArray
чтобы все данные, связанные с товарами, удаляются из кэша при обновлении любого отдельного элемента, связанного с ними. Например, метод GetProductsByCategoryID(categoryID)
кэширует экземпляры ProductsDataTables
для каждого уникального значения categoryID. Если один из этих объектов вытеснен, MasterCacheKeyArray
зависимость кэша гарантирует, что остальные также удаляются. Без этой зависимости кэша при изменении кэшированных данных существует вероятность того, что другие кэшированные данные продукта могут быть устаревшими. Следовательно, важно поддерживать MasterCacheKeyArray
зависимость кэша при использовании зависимостей кэша SQL. Однако метод кэширования данных Insert
позволяет лишь один объект зависимости.
Кроме того, при работе с зависимостями кэша SQL может потребоваться связать несколько таблиц базы данных с зависимостями. Например, ProductsDataTable
кэшированный в ProductsCL
классе содержит имена категорий и поставщиков для каждого продукта, но AddCacheItem
метод использует только зависимость Products
. В этом случае, если пользователь обновляет имя категории или поставщика, данные кэшированного продукта останутся в кэше и будут устаревшими. Поэтому мы хотим сделать кэшированные данные продукта зависящими не только от таблицы Products
, но и от таблиц Categories
и Suppliers
.
Класс AggregateCacheDependency
предоставляет средства для связывания нескольких зависимостей с элементом кэша. Начните с создания экземпляра AggregateCacheDependency
. Затем добавьте набор зависимостей с помощью AggregateCacheDependency
метода s Add
. При последующей вставке элемента в кэш данных, передайте экземпляр AggregateCacheDependency
. При изменении зависимостей любогоAggregateCacheDependency
экземпляра кэшированный элемент будет удалён.
Ниже показан обновленный код для ProductsCL
класса и метода AddCacheItem
. Метод создает зависимость кэша MasterCacheKeyArray
вместе с SqlCacheDependency
объектами для таблиц Products
, Categories
и Suppliers
. Все они объединяются в один AggregateCacheDependency
объект с именем aggregateDependencies
, который затем передается в Insert
метод.
Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
' Make sure MasterCacheKeyArray(0) is in the cache - if not, add it.
If DataCache(MasterCacheKeyArray(0)) Is Nothing Then
DataCache(MasterCacheKeyArray(0)) = DateTime.Now
End If
'Create the CacheDependency
Dim masterCacheKeyDependency As _
New Caching.CacheDependency(Nothing, MasterCacheKeyArray)
' Add the SqlCacheDependency objects for Products, Categories, and Suppliers
Dim productsTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Products")
Dim categoriesTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Categories")
Dim suppliersTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Suppliers")
' Create an AggregateCacheDependency
Dim aggregateDependencies As New Caching.AggregateCacheDependency()
aggregateDependencies.Add(masterCacheKeyDependency, productsTableDependency, _
categoriesTableDependency, suppliersTableDependency)
DataCache.Insert(GetCacheKey(rawKey), value, aggregateDependencies, _
Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration)
End Sub
Проверьте этот новый код. Теперь изменения в таблицах Products
, Categories
или Suppliers
вызывают вытеснение кэшированных данных. Кроме того, метод класса ProductsCL
, который вызывается при редактировании продукта через GridView, исключает зависимость кэша UpdateProduct
, что приводит к удалению кэшированных данных MasterCacheKeyArray
и повторному извлечению данных при следующем запросе.
Замечание
Зависимости кэша SQL также можно использовать с кэшированием выходных данных. Демонстрация этой функции см. в статье "Использование кэширования выходных данных ASP.NET с SQL Server".
Сводка
При кэшировании данных базы данных данные в идеале останутся в кэше, пока они не будут изменены в базе данных. При использовании ASP.NET 2.0 зависимости кэша SQL можно создавать и использовать как в декларативных, так и в программных сценариях. Одна из проблем с этим подходом заключается в обнаружении изменений данных. Полные версии Microsoft SQL Server 2005 предоставляют возможности уведомлений, которые могут оповещать приложение о изменении результата запроса. Для Express Edition SQL Server 2005 и более ранних релизов SQL Server вместо другого метода следует использовать систему опроса. К счастью, настройка необходимой инфраструктуры опроса довольно проста.
Счастливое программирование!
Дальнейшее чтение
Дополнительные сведения о разделах, описанных в этом руководстве, см. в следующих ресурсах:
- Использование уведомлений запросов в Microsoft SQL Server 2005
- Создание уведомления запроса
-
Кэширование в ASP.NET с
SqlCacheDependency
помощью класса -
ASP.NET средство регистрации SQL Server (
aspnet_regsql.exe
) -
Обзор
SqlCacheDependency
Сведения о авторе
Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга — Sams Teach Yourself ASP.NET 2.0 за 24 часа. С ним можно связаться по адресу mitchell@4GuysFromRolla.com.
Особое спасибо кому
Эта серия учебников была проверена многими полезными рецензентами. Ведущими рецензентами данного руководства были Марко Рейнджл, Тереса Мерфи и Хилтон Гизеноу. Хотите просмотреть мои предстоящие статьи MSDN? Если да, напишите мне на mitchell@4GuysFromRolla.com.