Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
La estrategia de almacenamiento en caché más sencilla es permitir que los datos almacenados en caché expiren después de un período de tiempo especificado. Pero este enfoque sencillo significa que los datos almacenados en caché no mantienen ninguna asociación con su origen de datos subyacente, lo que da lugar a datos obsoletos que se mantienen demasiado largos o actuales que han expirado demasiado pronto. Un mejor enfoque consiste en usar la clase SqlCacheDependency para que los datos permanezcan almacenados en caché hasta que sus datos subyacentes se hayan modificado en la base de datos SQL. En este tutorial se muestra cómo hacerlo.
Introducción
Las técnicas de almacenamiento en caché que se examinan en los tutoriales Caching Data with the ObjectDataSource y Caching Data in the Architecture utilizaron una expiración basada en el tiempo para expulsar los datos de la memoria caché después de un período especificado. Este enfoque es la manera más sencilla de equilibrar las ganancias de rendimiento del almacenamiento en caché frente a la obsolescencia de los datos. Al seleccionar una expiración de tiempo de x segundos, un desarrollador de páginas acepta disfrutar de las ventajas de rendimiento del caché durante solo x segundos, pero puede estar seguro de que sus datos nunca estarán obsoletos por un máximo de x segundos. Por supuesto, para los datos estáticos, x se puede extender a la duración de la aplicación web, como se examinó en el tutorial Datos de almacenamiento en caché en inicio de la aplicación.
Al almacenar en caché los datos de la base de datos, a menudo se elige una expiración basada en el tiempo para su facilidad de uso, pero suele ser una solución inadecuada. Idealmente, los datos de la base de datos permanecerán almacenados en caché hasta que los datos subyacentes se hayan modificado en la base de datos; solo entonces se expulsaría la memoria caché. Este enfoque maximiza las ventajas de rendimiento del almacenamiento en caché y minimiza la duración de los datos obsoletos. Sin embargo, para disfrutar de estas ventajas debe haber algún sistema que sepa cuándo se han modificado los datos de la base de datos subyacentes y expulsa los elementos correspondientes de la memoria caché. Antes de ASP.NET 2.0, los desarrolladores de páginas eran responsables de implementar este sistema.
ASP.NET 2.0 proporciona una SqlCacheDependency
clase y la infraestructura necesaria para determinar cuándo se ha producido un cambio en la base de datos para que se puedan expulsar los elementos almacenados en caché correspondientes. Existen dos técnicas para determinar cuándo han cambiado los datos subyacentes: notificación y sondeo. Después de analizar las diferencias entre la notificación y el sondeo, crearemos la infraestructura necesaria para admitir el sondeo y, a continuación, exploraremos cómo usar la SqlCacheDependency
clase en escenarios declarativos y mediante programación.
Descripción de las notificaciones y sondeos
Hay dos técnicas que se pueden usar para determinar cuándo se han modificado los datos de una base de datos: notificación y sondeo. Con la notificación, la base de datos alerta automáticamente al tiempo de ejecución de ASP.NET cuando se han cambiado los resultados de una consulta determinada desde que se ejecutó por última vez, momento en el que se eliminan los elementos almacenados en caché asociados a la consulta. Con el sondeo, el servidor de bases de datos mantiene información sobre cuándo se han actualizado por última vez tablas concretas. El runtime de ASP.NET sondea periódicamente la base de datos para comprobar qué tablas han cambiado desde que se introdujeron en la memoria caché. Esas tablas cuyos datos se han modificado tienen sus elementos de caché asociados expulsados.
La opción de notificación requiere menos configuración que el sondeo y es más granular, ya que realiza un seguimiento de los cambios en el nivel de consulta en lugar de en el nivel de tabla. Desafortunadamente, las notificaciones solo están disponibles en las ediciones completas de Microsoft SQL Server 2005 (es decir, las ediciones que no son Express). Sin embargo, la opción de sondeo se puede usar para todas las versiones de Microsoft SQL Server de 7.0 a 2005. Dado que estos tutoriales usan la edición Express de SQL Server 2005, nos centraremos en la configuración y el uso de la opción de sondeo. Consulte la sección Lectura adicional al final de este tutorial para obtener más recursos sobre las funcionalidades de notificación de SQL Server 2005.
Con el sondeo, la base de datos debe configurarse para incluir una tabla denominada AspNet_SqlCacheTablesForChangeNotification
que tiene tres columnas: tableName
, notificationCreated
y changeId
. Esta tabla contiene una fila para cada tabla que tiene datos que podrían necesitar usarse en una dependencia de caché de SQL en la aplicación web. La tableName
columna especifica el nombre de la tabla mientras notificationCreated
indica la fecha y hora en que se agregó la fila a la tabla. La changeId
columna es de tipo int
y tiene un valor inicial de 0. Su valor se incrementa con cada modificación en la tabla.
Además de la AspNet_SqlCacheTablesForChangeNotification
tabla, la base de datos también debe incluir desencadenadores en cada una de las tablas que pueden aparecer en una dependencia de caché de SQL. Estos desencadenadores se ejecutan cada vez que se inserta, actualiza o elimina una fila e incrementan el valor de la tabla en changeId
AspNet_SqlCacheTablesForChangeNotification
.
El entorno de ejecución de ASP.NET realiza un seguimiento del changeId
actual de una tabla al almacenar en caché los datos mediante un objeto SqlCacheDependency
. La base de datos se comprueba periódicamente y los SqlCacheDependency
objetos cuyos changeId
valores difieren del valor de la base de datos se expulsan, ya que un valor diferente changeId
indica que se ha producido un cambio en la tabla desde que se almacenaron en caché los datos.
Paso 1: Exploración del programa de la línea de comandos
Con el enfoque de sondeo, la base de datos debe configurarse para contener la infraestructura descrita anteriormente: una tabla predefinida (AspNet_SqlCacheTablesForChangeNotification
), un puñado de procedimientos almacenados y desencadenadores en cada una de las tablas que se pueden usar en dependencias de caché de SQL en la aplicación web. Estas tablas, procedimientos almacenados y desencadenadores se pueden crear a través del programa aspnet_regsql.exe
de línea de comandos , que se encuentra en la $WINDOWS$\Microsoft.NET\Framework\version
carpeta . Para crear la AspNet_SqlCacheTablesForChangeNotification
tabla y los procedimientos almacenados asociados, ejecute lo siguiente desde la línea de comandos:
/* 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
Nota:
Para ejecutar estos comandos, el inicio de sesión de base de datos especificado debe pertenecer a los roles db_securityadmin
y db_ddladmin
.
Por ejemplo, para agregar la infraestructura para sondear a una base de datos de Microsoft SQL Server denominada pubs
en un servidor de bases de datos denominado ScottsServer
mediante autenticación de Windows, vaya al directorio adecuado y, desde la línea de comandos, introduzca:
aspnet_regsql.exe -S ScottsServer -E -d pubs -ed
Una vez agregada la infraestructura de nivel de base de datos, es necesario agregar los desencadenadores a esas tablas que se usarán en las dependencias de la caché de SQL. Vuelva a usar el aspnet_regsql.exe
programa de línea de comandos, pero especifique el nombre de la tabla mediante la opción -t
y, en lugar de usar la opción -ed
, use -et
, de este modo:
/* 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
Para agregar los desencadenadores a las tablas authors
y titles
en la base de datos pubs
en ScottsServer
, use:
aspnet_regsql.exe -S ScottsServer -E -d pubs -t authors -et
aspnet_regsql.exe -S ScottsServer -E -d pubs -t titles -et
Para este tutorial, agregue los desencadenadores a las tablas Products
, Categories
y Suppliers
. Veremos la sintaxis de línea de comandos determinada en el paso 3.
Paso 2: Hacer referencia a una base de datos de Microsoft SQL Server 2005 Express Edition enApp_Data
El aspnet_regsql.exe
programa de línea de comandos requiere el nombre de la base de datos y del servidor para agregar la infraestructura de sondeo necesaria. Pero ¿cuál es el nombre de la base de datos y el servidor de una base de datos de Microsoft SQL Server 2005 Express que reside en la App_Data
carpeta? En lugar de tener que detectar cuáles son los nombres de base de datos y servidor, he encontrado que el enfoque más sencillo es adjuntar la base de datos a la localhost\SQLExpress
instancia de base de datos y cambiar el nombre de los datos mediante SQL Server Management Studio. Si tiene una de las versiones completas de SQL Server 2005 instaladas en el equipo, es probable que ya tenga SQL Server Management Studio instalado en el equipo. Si solo tiene la edición Express, puede descargar la versión gratuita de Microsoft SQL Server Management Studio.
Comience cerrando Visual Studio. A continuación, abra SQL Server Management Studio y elija conectarse al servidor mediante la localhost\SQLExpress
autenticación de Windows.
Figura 1: Conectar al localhost\SQLExpress
servidor
Después de conectarse al servidor, Management Studio mostrará el servidor y tendrá subcarpetas para las bases de datos, la seguridad, etc. Haga clic con el botón derecho en la carpeta Bases de datos y elija la opción Adjuntar. Se abrirá el cuadro de diálogo Adjuntar bases de datos (vea la figura 2). Haga clic en el botón Agregar y seleccione la NORTHWND.MDF
carpeta de la base de datos en la carpeta de la App_Data
aplicación web.
Figura 2: Adjuntar la NORTHWND.MDF
base de datos desde la carpeta (App_Data
imagen de tamaño completo)
Esto agregará la base de datos a la carpeta Bases de datos. El nombre de la base de datos puede ser la ruta de acceso completa al archivo de base de datos o la ruta de acceso completa precedida por un GUID. Para evitar tener que escribir este nombre de base de datos largo al usar la herramienta de línea de comandos de aspnet_regsql.exe, cambie el nombre de la base de datos a un nombre más descriptivo haciendo clic con el botón derecho en la base de datos simplemente adjuntada y seleccionando Cambiar nombre. He cambiado el nombre de mi base de datos a DataTutorials .
Figura 3: Cambiar el nombre de la base de datos adjunta a un nombre más Human-Friendly
Paso 3: Agregar la infraestructura de sondeo a la base de datos Northwind
Ahora que hemos adjuntado la NORTHWND.MDF
base de datos desde la App_Data
carpeta , estamos listos para agregar la infraestructura de sondeo. Suponiendo que ha cambiado el nombre de la base de datos a DataTutorials, ejecute los cuatro comandos siguientes:
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
Después de ejecutar estos cuatro comandos, haga clic con el botón derecho en el nombre de la base de datos en Management Studio, vaya al submenú Tareas y elija Separar. A continuación, cierre Management Studio y vuelva a abrir Visual Studio.
Una vez que Visual Studio se haya vuelto a abrir, explore en profundidad la base de datos a través del Explorador de servidores. Anote la nueva tabla (AspNet_SqlCacheTablesForChangeNotification
), los nuevos procedimientos almacenados y los desencadenadores en las Products
tablas , Categories
y Suppliers
.
Figura 4: La base de datos ahora incluye la infraestructura de sondeo necesaria
Paso 4: Configuración del servicio de sondeo
Después de crear las tablas, desencadenadores y procedimientos almacenados necesarios en la base de datos, el paso final es configurar el servicio de sondeo, que se realiza mediante Web.config
la especificación de las bases de datos que se van a usar y la frecuencia de sondeo en milisegundos. El código siguiente interroga la base de datos Northwind cada segundo.
<?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>
El name
valor del <add>
elemento ( NorthwindDB ) asocia un nombre legible a una base de datos determinada. Al trabajar con dependencias de caché de SQL, es necesario hacer referencia al nombre de la base de datos definido aquí, así como a la tabla en la que se basan los datos almacenados en caché. Veremos cómo usar la SqlCacheDependency
clase para asociar mediante programación las dependencias de caché de SQL con datos almacenados en caché en el paso 6.
Una vez establecida una dependencia de caché de SQL, el sistema de sondeo se conectará a las bases de datos definidas en los <databases>
elementos cada pollTime
milisegundos y ejecutará el AspNet_SqlCachePollingStoredProcedure
procedimiento almacenado. Este procedimiento almacenado que se agregó en el paso 3 mediante la herramienta de línea de comandos aspnet_regsql.exe
devuelve el valor tableName
y el valor changeId
para cada registro en AspNet_SqlCacheTablesForChangeNotification
. Las dependencias obsoletas de la caché de SQL se expulsan de la memoria caché.
La pollTime
configuración presenta un equilibrio entre el rendimiento y la obsolescencia de los datos. Un valor pequeño pollTime
aumenta el número de solicitudes a la base de datos, pero más rápidamente expulsa los datos obsoletos de la memoria caché. Un valor mayor pollTime
reduce el número de solicitudes de base de datos, pero aumenta el retraso entre cuando cambian los datos de back-end y cuando se expulsan los elementos de caché relacionados. Afortunadamente, la solicitud de base de datos ejecuta un procedimiento almacenado sencillo que devuelve solo unas pocas filas de una tabla simple y ligera. Pero experimente con valores diferentes pollTime
para encontrar un equilibrio ideal entre el acceso a la base de datos y la obsolescencia de los datos para la aplicación. El valor más pollTime
pequeño permitido es 500.
Nota:
En el ejemplo anterior se proporciona un único pollTime
valor en el <sqlCacheDependency>
elemento , pero opcionalmente puede especificar el pollTime
valor en el <add>
elemento . Esto resulta útil si tiene varias bases de datos especificadas y desea personalizar la frecuencia de sondeo por base de datos.
Paso 5: Trabajar mediante declaración con dependencias de caché de SQL
En los pasos 1 a 4 hemos visto cómo configurar la infraestructura de base de datos necesaria y configurar el sistema de sondeo. Con esta infraestructura establecida, ahora podemos agregar elementos a la caché de datos con una dependencia de caché SQL asociada mediante técnicas programáticas o declarativas. En este paso, examinaremos cómo trabajar mediante declaración con dependencias de caché de SQL. En el paso 6 veremos el enfoque mediante programación.
El tutorial Almacenamiento en caché de datos con ObjectDataSource ha explorado las funcionalidades declarativas de almacenamiento en caché de ObjectDataSource. Simplemente estableciendo la EnableCaching
propiedad en True
y la CacheDuration
propiedad en algún intervalo de tiempo, ObjectDataSource almacenará automáticamente en caché los datos devueltos desde su objeto subyacente para el intervalo especificado. ObjectDataSource también puede usar una o varias dependencias de caché de SQL.
Para demostrar el uso de las dependencias de caché de SQL de manera declarativa, abra la página SqlCacheDependencies.aspx
en la carpeta Caching
y arrastre un control GridView desde el cuadro de herramientas al Diseñador. Establezca el GridView en ID
, ProductsDeclarative
y, desde su etiqueta inteligente, elija enlazarlo a un nuevo ObjectDataSource denominado ProductsDataSourceDeclarative
.
Figura 5: crear un nuevo ObjectDataSource denominado ProductsDataSourceDeclarative
(haga clic para ver la imagen a tamaño completo)
Configure el ObjectDataSource para usar la clase ProductsBLL
y en la pestaña SELECT, establezca la lista desplegable en GetProducts()
. En la pestaña UPDATE, elija la UpdateProduct
sobrecarga con tres parámetros de entrada: productName
, unitPrice
, y productID
. Establezca las listas desplegables en (Ninguno) en las pestañas INSERT y DELETE.
Figura 6: Utilice la sobrecarga UpdateProduct con tres parámetros de entrada (haga clic para ver la imagen en tamaño completo)
Figura 7: Establecer la lista de Drop-Down en (Ninguno) para las pestañas INSERT y DELETE (Haga clic para ver la imagen de tamaño completo)
Después de completar el Asistente para configurar orígenes de datos, Visual Studio creará BoundFields y CheckBoxFields en GridView para cada uno de los campos de datos. Quite todos los campos excepto ProductName
, CategoryName
, y UnitPrice
, y dé formato a estos campos según se ajuste. En la etiqueta inteligente GridView, active las casillas Habilitar paginación, Habilitar ordenación y Habilitar edición. Visual Studio establecerá la propiedad ObjectDataSource s OldValuesParameterFormatString
en original_{0}
. Para que la característica de edición de GridView funcione correctamente, quite esta propiedad completamente de la sintaxis declarativa o establézcala de nuevo en su valor predeterminado, {0}
.
Por último, agregue un control Web Label encima del GridView y establezca su propiedad ID
en ODSEvents
, y su propiedad EnableViewState
en False
. Después de realizar estos cambios, el marcado declarativo de la página debe ser similar al siguiente. Tenga en cuenta que he realizado una serie de personalizaciones estéticas en los campos GridView que no son necesarios para demostrar la funcionalidad de dependencia de caché de 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>
A continuación, cree un controlador de eventos para el evento Selecting
de ObjectDataSource y, en él, agregue el siguiente código:
Protected Sub ProductsDataSourceDeclarative_Selecting _
(sender As Object, e As ObjectDataSourceSelectingEventArgs) _
Handles ProductsDataSourceDeclarative.Selecting
ODSEvents.Text = "-- Selecting event fired"
End Sub
Recuerde que el evento Selecting
de ObjectDataSource se activa solamente al recuperar datos de su objeto subyacente. Si ObjectDataSource tiene acceso a los datos desde su propia memoria caché, este evento no se desencadena.
Ahora, visite esta página a través de un explorador. Como aún no hemos implementado ningún almacenamiento en caché, cada vez que se pagine, ordene o edite la cuadrícula, la página debería mostrar el texto "Evento de selección activado", tal como se muestra en la figura 8.
Figura 8: El evento de ObjectDataSource se Selecting
desencadena cada vez que el GridView está paginado, editado o ordenado (haga clic para ver la imagen en tamaño completo).
Como vimos en el tutorial Datos de almacenamiento en caché con ObjectDataSource , establecer la EnableCaching
propiedad en True
hace que ObjectDataSource almacene en caché sus datos durante la duración especificada por su CacheDuration
propiedad. ObjectDataSource también tiene una SqlCacheDependency
propiedad , que agrega una o varias dependencias de caché de SQL a los datos almacenados en caché mediante el patrón :
databaseName1:tableName1;databaseName2:tableName2;...
Donde databaseName es el nombre de la base de datos tal como se especifica en el name
atributo del <add>
elemento en Web.config
y tableName es el nombre de la tabla de base de datos. Por ejemplo, para crear un ObjectDataSource que almacene en caché los datos indefinidamente en función de una dependencia de caché de SQL en la tabla Northwind sProducts
, establezca la propiedad ObjectDataSource en EnableCaching
y la propiedad True
en NorthwindDB:Products.
Nota:
Puede usar una dependencia de caché de SQL y una expiración basada en el tiempo estableciendo EnableCaching
en True
, CacheDuration
para el intervalo de tiempo y SqlCacheDependency
para los nombres de la base de datos y de la tabla. ObjectDataSource expulsará sus datos cuando se alcance la expiración basada en el tiempo o cuando el sistema de sondeo tenga en cuenta que los datos de la base de datos subyacentes han cambiado, lo que ocurra primero.
GridView en SqlCacheDependencies.aspx
muestra los datos de dos tablas - Products
y Categories
(el campo CategoryName
del producto se recupera a través de un JOIN
en Categories
). Por lo tanto, queremos especificar dos dependencias de caché de SQL: NorthwindDB:Products; NorthwindDB:Categories .
Figura 9: Configurar objectDataSource para admitir el almacenamiento en caché mediante dependencias de caché de SQL en Products
y Categories
(haga clic para ver la imagen de tamaño completo)
Después de configurar ObjectDataSource para admitir el almacenamiento en caché, vuelva a visitar la página a través de un explorador. De nuevo, el texto "Seleccionar evento desencadenado" debe aparecer en la primera visita de la página, pero debe desaparecer al paginar, ordenar o hacer clic en los botones Editar o Cancelar. Esto se debe a que después de cargar los datos en la memoria caché de ObjectDataSource, permanece allí hasta que las Products
tablas o Categories
se modifican o los datos se actualizan a través de GridView.
Después de navegar por la cuadrícula y observar la falta del texto 'Evento de selección activado', abra una nueva ventana del navegador y vaya al tutorial Aspectos básicos en la sección de Edición, Inserción y Eliminación (~/EditInsertDelete/Basics.aspx
). Actualice el nombre o el precio de un producto. A continuación, desde la primera ventana del navegador, visualice una página diferente de datos, ordene la cuadrícula o haga clic en el botón Editar de una fila. Esta vez, el evento de selección desencadenado debe volver a aparecer, ya que se han modificado los datos de la base de datos subyacentes (vea la figura 10). Si el texto no aparece, espere unos instantes e inténtelo de nuevo. Recuerde que el servicio de sondeo comprueba si hay cambios en la Products
tabla cada pollTime
milisegundos, por lo que hay un retraso entre cuándo se actualizan los datos subyacentes y cuándo se expulsan los datos almacenados en caché.
Figura 10: Modificar la tabla products expulsa los datos de producto almacenados en caché (haga clic para ver la imagen de tamaño completo)
Paso 6: Trabajar mediante programación con laSqlCacheDependency
clase
En el tutorial Almacenamiento en caché de datos en la arquitectura, se examinan las ventajas de usar una capa de almacenamiento en caché independiente en la arquitectura, en lugar de acoplar estrechamente el almacenamiento en caché con ObjectDataSource. En ese tutorial hemos creado una ProductsCL
clase para mostrar cómo trabajar mediante programación con la caché de datos. Para usar dependencias de caché de SQL en la capa de almacenamiento en caché, use la SqlCacheDependency
clase .
Con el sistema de sondeo, un SqlCacheDependency
objeto debe estar asociado a un par de bases de datos y tablas concretos. El código siguiente, por ejemplo, crea un SqlCacheDependency
objeto basado en la tabla de Products
la base de datos Northwind:
Dim productsTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Products")
Los dos parámetros de entrada para el SqlCacheDependency
constructor s son los nombres de base de datos y tabla, respectivamente. Al igual que con la propiedad SqlCacheDependency
de ObjectDataSource, el nombre de la base de datos usado es el mismo que el valor especificado en el atributo name
del elemento <add>
en Web.config
. El nombre de la tabla es el nombre real de la tabla de base de datos.
Para asociar un SqlCacheDependency
con un elemento agregado a la memoria caché de datos, use una de las sobrecargas del método Insert
que acepta una dependencia. El código siguiente agrega valor a la memoria caché de datos durante una duración indefinida, pero lo asocia con un SqlCacheDependency
en la tabla Products
. En resumen, el valor permanecerá en la memoria caché hasta que se expulse debido a restricciones de memoria o porque el sistema de sondeo ha detectado que la Products
tabla ha cambiado desde que se ha almacenado en caché.
Dim productsTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Products")
Cache.Insert(key, _
value, _
productsTableDependency, _
System.Web.Caching.Cache.NoAbsoluteExpiration, _
System.Web.Caching.Cache.NoSlidingExpiration)
En la clase ProductsCL
Caching Layer, actualmente se almacenan en caché los datos de la tabla Products
utilizando una expiración basada en el tiempo de 60 segundos. Vamos a actualizar esta clase para que use dependencias de caché de SQL en su lugar. El ProductsCL
método de la clase s AddCacheItem
, que es responsable de agregar los datos a la memoria caché, contiene actualmente el código siguiente:
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
Actualice este código para usar un SqlCacheDependency
objeto en lugar de la MasterCacheKeyArray
dependencia de caché:
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
Para probar esta funcionalidad, agregue una clase GridView a la página situada debajo de GridView existente ProductsDeclarative
. Establezca ID
de este nuevo GridView en ProductsProgrammatic
y, a través de su etiqueta inteligente, vínculelo a un nuevo ObjectDataSource denominado ProductsDataSourceProgrammatic
. Configure ObjectDataSource para usar la clase ProductsCL
, estableciendo las listas desplegables en las pestañas SELECT y UPDATE en GetProducts
y UpdateProduct
, respectivamente.
Figura 11: Configurar objectDataSource para usar la clase (ProductsCL
la imagen de tamaño completo)
Figura 12: Seleccionar el GetProducts
método de la lista de Drop-Down de la pestaña SELECT (haga clic para ver la imagen de tamaño completo)
Figura 13: Elegir el método UpdateProduct en la lista de Drop-Down pestaña UPDATE (haga clic para ver la imagen de tamaño completo)
Después de completar el Asistente para configurar orígenes de datos, Visual Studio creará BoundFields y CheckBoxFields en GridView para cada uno de los campos de datos. Al igual que con el primer GridView agregado a esta página, quite todos los campos excepto ProductName
, CategoryName
y UnitPrice
, y dé formato a estos campos como considere apropiado. En la etiqueta inteligente GridView, active las casillas Habilitar paginación, Habilitar ordenación y Habilitar edición. Al igual que con ProductsDataSourceDeclarative
ObjectDataSource, Visual Studio establecerá la ProductsDataSourceProgrammatic
propiedad de OldValuesParameterFormatString
ObjectDataSource a original_{0}
. Para que la característica de edición de GridView funcione correctamente, restablezca esta propiedad a {0}
o elimine por completo la asignación de la propiedad en la sintaxis declarativa.
Después de completar estas tareas, el marcado declarativo GridView y ObjectDataSource resultante debe ser similar al siguiente:
<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>
Para probar la dependencia de caché de SQL en la capa de almacenamiento en caché, establezca un punto de interrupción en el método de la ProductCL
clase s AddCacheItem
y, a continuación, inicie la depuración. Cuando visite por primera vez SqlCacheDependencies.aspx
, el punto de interrupción debería activarse cuando se soliciten los datos y se coloquen en la memoria caché. A continuación, vaya a otra página de GridView o ordene una de las columnas. Esto hace que GridView vuelva a consultar sus datos, pero los datos se deben encontrar en la caché, ya que la tabla de base de datos Products
no se ha modificado. Si los datos no se encuentran repetidamente en la memoria caché, asegúrese de que hay suficiente memoria disponible en el equipo e inténtelo de nuevo.
Después de paginar a través de algunas páginas de GridView, abra una segunda ventana del explorador y vaya al tutorial Aspectos básicos en la sección Edición, Inserción y Eliminación (~/EditInsertDelete/Basics.aspx
). Actualice un registro de la tabla Products y, a continuación, desde la primera ventana del explorador, vea una nueva página o haga clic en uno de los encabezados de ordenación.
En este escenario verá una de las dos cosas: se alcanzará el punto de interrupción, lo que indica que los datos almacenados en caché se expulsaron debido al cambio en la base de datos; o bien, el punto de interrupción no se alcanzará, lo que significa que SqlCacheDependencies.aspx
ahora muestra datos obsoletos. Si no se alcanza el punto de interrupción, es probable que el servicio de sondeo aún no se haya activado porque los datos han sido recientemente modificados. Recuerde que el servicio de sondeo comprueba si hay cambios en la Products
tabla cada pollTime
milisegundos, por lo que hay un retraso entre cuándo se actualizan los datos subyacentes y cuándo se expulsan los datos almacenados en caché.
Nota:
Este retraso es más probable que aparezca al editar uno de los productos a través de GridView en SqlCacheDependencies.aspx
. En el tutorial De almacenamiento en caché de datos en la arquitectura, agregamos la MasterCacheKeyArray
dependencia de caché para asegurarnos de que los datos que se editan a través del método de la ProductsCL
clase se fueron UpdateProduct
expulsados de la memoria caché. Sin embargo, reemplazamos esta dependencia de caché al modificar el AddCacheItem
método anterior en este paso y, por lo tanto, la ProductsCL
clase seguirá mostrando los datos almacenados en caché hasta que el sistema de sondeo adiga el cambio en la Products
tabla. Veremos cómo volver a introducir la MasterCacheKeyArray
dependencia de caché en el paso 7.
Paso 7: Asociar varias dependencias con un elemento almacenado en caché
Recuerde que la MasterCacheKeyArray
dependencia de caché se usa para asegurarse de que todos los datos relacionados con el producto se expulsan de la memoria caché cuando se actualiza cualquier elemento único asociado dentro de él. Por ejemplo, el GetProductsByCategoryID(categoryID)
método almacena en caché las ProductsDataTables
instancias de cada valor categoryID único. Si se expulsa uno de estos objetos, la MasterCacheKeyArray
dependencia de caché garantiza que los demás también se eliminen. Sin esta dependencia de caché, cuando se modifican los datos almacenados en caché, existe la posibilidad de que otros datos del producto almacenados en caché no estén actualizados. Por lo tanto, es importante mantener la dependencia de caché MasterCacheKeyArray
al usar dependencias de caché de SQL. Sin embargo, el método de la caché de datos Insert
solo permite un único objeto de dependencia.
Además, al trabajar con dependencias de caché de SQL, es posible que tengamos que asociar varias tablas de base de datos como dependencias. Por ejemplo, la ProductsDataTable
memoria caché de la ProductsCL
clase contiene los nombres de categoría y proveedor de cada producto, pero el AddCacheItem
método solo usa una dependencia en Products
. En esta situación, si el usuario actualiza el nombre de una categoría o proveedor, los datos del producto almacenados en caché permanecerán en la memoria caché y estarán obsoletos. Por lo tanto, queremos hacer que los datos del producto almacenados en caché dependan no solo de la Products
tabla, sino también de las Categories
tablas y Suppliers
.
La AggregateCacheDependency
clase proporciona un medio para asociar varias dependencias con un elemento de caché. Empiece por crear una AggregateCacheDependency
instancia. A continuación, agregue el conjunto de dependencias mediante el AggregateCacheDependency
método s Add
. Después de insertar el elemento en la memoria caché de datos, pase la instancia de AggregateCacheDependency
. Cuando cambie cualquiera de las dependencias de la AggregateCacheDependency
instancia, se expulsará el elemento almacenado en caché.
A continuación se muestra el código actualizado para el método de la ProductsCL
clase s AddCacheItem
. El método crea la MasterCacheKeyArray
dependencia de caché junto con SqlCacheDependency
objetos para las Products
tablas, Categories
y Suppliers
. Todos se combinan en un AggregateCacheDependency
objeto denominado aggregateDependencies
, que luego se pasa al Insert
método .
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
Pruebe este nuevo código. Ahora, los cambios realizados en las Products
tablas , Categories
o Suppliers
hacen que los datos almacenados en caché se expulsen. Además, el método de la ProductsCL
clase s UpdateProduct
, al que se llama al editar un producto a través de GridView, expulsa la MasterCacheKeyArray
dependencia de caché, lo que hace que se expulse la memoria caché ProductsDataTable
y se vuelvan a recuperar los datos en la siguiente solicitud.
Nota:
Las dependencias de caché de SQL también se pueden usar con el almacenamiento en caché de salida. Para obtener una demostración de esta funcionalidad, consulte : Uso del almacenamiento en caché de salida ASP.NET con SQL Server.
Resumen
Al almacenar en caché los datos de la base de datos, los datos permanecerán idealmente en la memoria caché hasta que se modifiquen en la base de datos. Con ASP.NET 2.0, se pueden crear y usar dependencias de caché de SQL en escenarios declarativos y mediante programación. Uno de los desafíos de este enfoque es detectar cuándo se han modificado los datos. Las versiones completas de Microsoft SQL Server 2005 proporcionan funcionalidades de notificación que pueden alertar a una aplicación cuando ha cambiado un resultado de consulta. Para la edición Express de SQL Server 2005 y versiones anteriores de SQL Server, se debe usar en su lugar un sistema de sondeo. Afortunadamente, configurar la infraestructura de sondeo necesaria es bastante sencilla.
¡Feliz programación!
Lecturas adicionales
Para obtener más información sobre los temas tratados en este tutorial, consulte los siguientes recursos:
- Uso de notificaciones de consulta en Microsoft SQL Server 2005
- Creación de una notificación de consulta
-
Almacenamiento en caché en ASP.NET con la
SqlCacheDependency
clase -
herramienta de registro de SQL Server () de ASP.NET (
aspnet_regsql.exe
) -
Información general de
SqlCacheDependency
Acerca del autor
Scott Mitchell, autor de siete libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 en 24 horas. Se puede contactar con él en mitchell@4GuysFromRolla.com.
Agradecimientos especiales a
Esta serie de tutoriales contó con la revisión de muchos revisores que fueron de gran ayuda. Los principales revisores de este tutorial fueron Marko Rangel, Teresa Murphy y Hilton Giesenow. ¿Le interesa revisar mis próximos artículos de MSDN? Si es así, mándame un mensaje a mitchell@4GuysFromRolla.com.