Использование зависимостей кэша SQL (VB)
Самая простая стратегия кэширования — разрешить истечение срока действия кэшированных данных по истечении указанного периода времени. Но этот простой подход означает, что кэшированные данные не поддерживают связь с базовым источником данных, что приводит к тому, что устаревшие данные хранятся слишком долго или текущие данные, срок действия которых истек слишком рано. Лучший подход — использовать класс 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. Так как в этих руководствах используется выпуск Express SQL Server 2005, мы сосредоточимся на настройке и использовании параметра опроса. Дополнительные ресурсы по возможностям уведомлений 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
.
Например, чтобы добавить инфраструктуру для опроса в базу данных pubs
Microsoft SQL Server на сервере базы данных с именем с помощью 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
в базе данных ScottsServer
в pubs
, используйте:
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, экспресс-выпуск в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, вы можете скачать бесплатный 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 необходимо ссылаться на имя базы данных, определенное здесь, а также на таблицу, на основе которую основаны кэшированные данные. На шаге 6 мы рассмотрим, как использовать класс для программного SqlCacheDependency
связывания зависимостей кэша SQL с кэшируемыми данными.
После установки зависимости кэша 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 с панели элементов на Designer. Задайте для gridView значение ID
ProductsDeclarative
и из смарт-тега привяжите его к новому объекту ObjectDataSource с именем ProductsDataSourceDeclarative
.
Рис. 5. Создание объекта ObjectDataSource с именем ProductsDataSourceDeclarative
(щелкните для просмотра полноразмерного изображения)
Настройте ObjectDataSource для использования ProductsBLL
класса и задайте для раскрывающегося списка на вкладке SELECT значение GetProducts()
. На вкладке ОБНОВЛЕНИЕ выберите перегрузку UpdateProduct
с тремя входными параметрами : productName
, unitPrice
и productID
. Установите для раскрывающихся списков значение (Нет) на вкладках INSERT и DELETE.
Рис. 6. Использование перегрузки UpdateProduct с тремя входными параметрами (щелкните для просмотра полноразмерного изображения)
Рис. 7. Задайте для Drop-Down List значение (Нет) для вкладок INSERT и DELETE (Щелкните для просмотра полноразмерного изображения)
После завершения работы мастера настройки источника данных Visual Studio создаст BoundFields и CheckBoxFields в GridView для каждого поля данных. Удалите все поля, кроме ProductName
, CategoryName
и , и UnitPrice
отформатируйте эти поля так, как вы считаете нужным. В смарт-теге GridView проверка флажки Включить разбиение по страницам, Включить сортировку и Включить редактирование. Visual Studio установит для свойства ObjectDataSource значение OldValuesParameterFormatString
original_{0}
. Чтобы функция редактирования GridView работала правильно, либо полностью удалите это свойство из декларативного синтаксиса, либо присвойте ему значение {0}
по умолчанию .
Наконец, добавьте элемент управления Label Web над 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
срабатывает только при получении данных из базового объекта. Если ObjectDataSource обращается к данным из собственного кэша, это событие не запускается.
Теперь перейдите на эту страницу через браузер. Так как мы еще не реализовали кэширование, каждый раз, когда вы страницы, сортировки или изменения сетки, на странице должен отображаться текст "Выбор события, как показано на рисунке 8.
Рис. 8. Событие ObjectDataSource Selecting
срабатывает каждый раз, когда GridView выстраивается, редактируется или сортируется (щелкните, чтобы просмотреть полноразмерное изображение)
Как мы видели в руководстве по кэшированию данных в objectDataSource , установка EnableCaching
свойства в True
значение приводит к тому, что ObjectDataSource будет кэшировать свои данные в течение времени, указанного его CacheDuration
свойством. ObjectDataSource также имеет SqlCacheDependency
свойство , которое добавляет одну или несколько зависимостей кэша SQL к кэшируемым данным с помощью шаблона :
databaseName1:tableName1;databaseName2:tableName2;...
Где databaseName — это имя базы данных, указанное в name
атрибуте <add>
элемента в Web.config
, а tableName — имя таблицы базы данных. Например, чтобы создать объект ObjectDataSource, который кэширует данные на неопределенный срок на основе зависимости кэша Products
SQL от таблицы Northwind, присвойте свойству ObjectDataSource EnableCaching
значение True
, а его SqlCacheDependency
свойству — NorthwindDB:Products .
Примечание
Вы можете использовать зависимость кэша SQL и срок действия на основе времени, задав значение EnableCaching
True
, CacheDuration
для интервала времени, а SqlCacheDependency
также для имен баз данных и таблиц. ObjectDataSource будет вытеснить свои данные по истечении срока действия на основе времени или когда система опроса отмечает, что базовые данные базы данных изменились, в зависимости от того, что произойдет в первую очередь.
GridView в отображает SqlCacheDependencies.aspx
данные из двух таблиц — Products
и Categories
(поле products CategoryName
извлекается через JOIN
в Categories
). Поэтому необходимо указать две зависимости кэша SQL: NorthwindDB:Products; NorthwindDB:Категории .
Рис. 9. Настройка ObjectDataSource для поддержки кэширования с помощью зависимостей Products
кэша SQL для и Categories
(щелкните для просмотра полноразмерного изображения)
Настроив ObjectDataSource для поддержки кэширования, вернитесь на страницу через браузер. Опять же, текст "Сработавшее событие выбора" должен отображаться при первом посещении страницы, но должен исчезнуть при разбиении по страницам, сортировке или нажатии кнопок Изменить или Отмена. Это связано с тем, что после загрузки данных в кэш ObjectDataSource они остаются там до тех пор, пока Products
таблицы или не Categories
будут изменены или данные не будут обновлены с помощью GridView.
После разбиения по страницам сетки и замечая отсутствие сработающего текста "Выбор события", откройте новое окно браузера и перейдите к учебнику Основные сведения в разделе Редактирование, вставка и удаление (~/EditInsertDelete/Basics.aspx
). Обновите название или цену продукта. Затем в первом окне браузера просмотрите другую страницу данных, отсортируйте сетку или нажмите кнопку Изменить в строке. На этот раз должно появиться событие Selecting , так как базовые данные базы данных были изменены (см. рис. 10). Если текст не отображается, подождите несколько секунд и повторите попытку. Помните, что служба опроса проверяет наличие изменений в Products
таблице каждые pollTime
миллисекунды, поэтому между обновлением базовых данных и удалением кэшированных данных существует задержка.
Рис. 10. Изменение таблицы Products удаляет кэшированные данные о продукте (щелкните, чтобы просмотреть полноразмерное изображение)
Шаг 6. Программная работа с классомSqlCacheDependency
В руководстве по кэшированию данных в учебнике по архитектуре были описаны преимущества использования отдельного слоя кэширования в архитектуре, а не тесного связывания кэширования с ObjectDataSource. В этом руководстве мы создали класс для ProductsCL
демонстрации программной работы с кэшем данных. Чтобы использовать зависимости кэша SQL на уровне кэширования, используйте SqlCacheDependency
класс .
В опрашивочной системе SqlCacheDependency
объект должен быть связан с определенной парой базы данных и таблицы. Например, следующий код создает SqlCacheDependency
объект на основе таблицы базы данных Products
Northwind:
Dim productsTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Products")
Два входных параметра конструктора SqlCacheDependency
— это имена базы данных и таблицы соответственно. Как и в случае со свойством ObjectDataSource SqlCacheDependency
, используемое имя базы данных совпадает со значением, указанным в 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)
Класс Caching Layer в 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
класса , установив для раскрывающихся списков на вкладках SELECT и UPDATE значения GetProducts
и UpdateProduct
соответственно.
Рис. 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 присвоит свойству original_{0}
ProductsDataSourceProgrammatic
ObjectDataSource значение OldValuesParameterFormatString
. Чтобы функция редактирования 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
метода класса s 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
метод класса UpdateProduct
, который вызывается при редактировании продукта с помощью GridView, вытесняя MasterCacheKeyArray
зависимость кэша, что приводит к вытеснениям кэша ProductsDataTable
и повторному извлечению данных при следующем запросе.
Примечание
Зависимости кэша 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
Об авторе
Скотт Митчелл (Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с Веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часа. Его можно связать по адресу mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.
Отдельная благодарность
Эта серия учебников была проверена многими полезными рецензентами. В качестве ведущих рецензентов этого руководства были Марко Рейнджл, Тереса Мерфи и Хилтон Гизеноу. Хотите ознакомиться с моими предстоящими статьями MSDN? Если да, опустите мне строку в mitchell@4GuysFromRolla.com.