Almacenar datos en caché en la arquitectura (VB)

por Scott Mitchell

Descargar PDF

En el tutorial anterior, hemos aprendido a aplicar el almacenamiento en caché en la capa de presentación. En este tutorial, aprenderemos a aprovechar nuestra arquitectura en capas para almacenar en caché los datos en la capa de lógica empresarial. Para ello, ampliamos la arquitectura para incluir una capa de caché.

Introducción

Como hemos visto en el tutorial anterior, el almacenamiento en caché de los datos de ObjectDataSource es tan sencillo como establecer un par de propiedades. Desafortunadamente, ObjectDataSource aplica el almacenamiento en caché en la capa de presentación, que acopla estrechamente las directivas de caché con la página ASP.NET. Una de las razones para crear una arquitectura en capas es permitir que estos acoplamientos se rompan. La capa de lógica empresarial, por ejemplo, desacopla la lógica empresarial de las páginas de ASP.NET, mientras que la capa de acceso a datos desacopla los detalles de acceso a datos. Este desacoplamiento de la lógica empresarial y los detalles de acceso a datos es preferible, en parte, porque permite que el sistema sea más legible, más fácil de mantener y más flexible a la hora de cambiar. También permite el conocimiento del dominio y la división del trabajo, ya que un desarrollador que trabaja en la capa de presentación no necesita estar familiarizado con los detalles de la base de datos para realizar su trabajo. Desacoplar la directiva de almacenamiento en caché de la capa de presentación ofrece ventajas similares.

En este tutorial, vamos a aumentar nuestra arquitectura para incluir una capa de caché (o CL para abreviar) que utiliza nuestra directiva de almacenamiento en caché. La capa de caché incluirá una clase ProductsCL que proporciona acceso a la información del producto con métodos como GetProducts(), GetProductsByCategoryID(categoryID), etc., que, cuando se invocan, primero intentarán recuperar los datos de la caché. Si la caché está vacía, estos métodos invocarán el método ProductsBLL correspondiente en BLL, que a su vez obtendrá los datos de DAL. Los métodos ProductsCL almacenan en caché los datos recuperados de BLL antes de devolverlos.

Como se muestra en la figura 1, la CL reside entre las capas de presentación y lógica empresarial.

The Caching Layer (CL) is Another Layer in Our Architecture

Figura 1: La capa de caché (CL) es otra capa en nuestra arquitectura

Paso 1: Crear las clases de capa de caché

En este tutorial, crearemos una CL muy sencilla con una sola clase ProductsCL que solo tiene unos pocos métodos. La creación de una capa de caché completa para toda la aplicación requerirá crear las clases CategoriesCL, EmployeesCL y SuppliersCL, y proporcionar un método en estas clases de capa de caché para cada método de acceso o modificación de datos en BLL. Al igual que con BLL y DAL, la capa de caché debe implementarse idealmente como un proyecto de biblioteca de clases independiente; sin embargo, lo implementaremos como una clase en la carpeta App_Code.

Para separar más limpiamente las clases CL de las clases DAL y BLL, vamos a crear una subcarpeta en la carpeta App_Code. Haga clic con el botón derecho en la carpeta App_Code del Explorador de soluciones, elija Nueva carpeta y llame a la nueva carpeta CL. Después de crear esta carpeta, añádala a una nueva clase denominada ProductsCL.vb.

Add a New Folder Named CL and a Class Named ProductsCL.vb

Figura 2: Añadir una nueva carpeta denominada CL y una clase denominada ProductsCL.vb

La clase ProductsCL debe incluir el mismo conjunto de métodos de acceso y modificación de datos que se encuentran en su clase de capa de lógica empresarial correspondiente (ProductsBLL). En lugar de crear todos estos métodos, vamos a crear un par aquí para hacernos una idea de los patrones usados por la CL. En concreto, añadiremos los métodos GetProducts() yGetProductsByCategoryID(categoryID) en el paso 3 y una sobrecarga de UpdateProduct en el paso 4. Puede añadir los métodos ProductsCL restantes y las clases CategoriesCL, EmployeesCL y SuppliersCL en su tiempo libre.

Paso 2: Leer y escribir en la caché de datos

La característica de almacenamiento en caché ObjectDataSource explorada en el tutorial anterior usa internamente la caché de datos de ASP.NET para almacenar los datos recuperados de BLL. También se puede acceder a la caché de datos mediante programación desde las clases de código subyacente de las páginas de ASP.NET o desde las clases en la arquitectura de la aplicación web. Para leer y escribir en la caché de datos desde una clase de código subyacente de una página ASP.NET, use el siguiente patrón:

' Read from the cache
Dim value as Object = Cache("key")
' Add a new item to the cache
Cache("key") = value
Cache.Insert(key, value)
Cache.Insert(key, value, CacheDependency)
Cache.Insert(key, value, CacheDependency, DateTime, TimeSpan)

El método Insert de la clase Cache tiene varias sobrecargas. Cache("key") = value y Cache.Insert(key, value) son sinónimos y ambos añaden un elemento a la caché utilizando la clave especificada sin una expiración definida. Normalmente, queremos especificar una expiración al agregar un elemento a la caché, ya sea como una dependencia, una expiración basada en el tiempo o ambas. Use una de las otras sobrecargas del método Insert para proporcionar información de expiración basada en dependencias o en el tiempo.

Los métodos de la capa de caché deben comprobar primero si los datos solicitados están en la caché y, si es así, devolverlos desde ahí. Si los datos solicitados no están en la caché, se debe invocar el método BLL adecuado. Su valor devuelto debe almacenarse en caché y, a continuación, devolverse como se muestra en el diagrama de secuencia siguiente.

The Caching Layer s Methods Return Data from the Cache if it s Available

Figura 3: Los métodos de la capa de caché devuelven datos de la caché si están disponibles

La secuencia que se muestra en la figura 3 se realiza en las clases CL utilizando el siguiente patrón:

Dim instance As Type = TryCast(Cache("key"), Type)
If instance Is Nothing Then
    instance = BllMethodToGetInstance()
    Cache.Insert(key, instance, ...)
End If
Return instance

Aquí, Type es el tipo de datos que se almacenan en la caché Northwind.ProductsDataTable, por ejemplo, mientras que key es la clave que identifica de forma única el elemento de caché. Si el elemento con la key especificada no está en la caché, instance será Nothing, y los datos se recuperarán del método BLL correspondiente y se añadirán a la caché. Cuando se alcanza el tiempo Return instance, instance contiene una referencia a los datos, ya sea de la memoria caché o extraída de BLL.

Asegúrese de usar el patrón anterior cuando acceda a los datos de la caché. El siguiente patrón, que, a primera vista, parece equivalente, contiene una diferencia sutil que introduce una condición de carrera. Las condiciones de carrera son difíciles de depurar, porque se revelan esporádicamente y son difíciles de reproducir.

If Cache("key") Is Nothing Then
    Cache.Insert(key, BllMethodToGetInstance(), ...)
End If
Return Cache("key")

La diferencia en este segundo fragmento de código incorrecto es que, en lugar de almacenar una referencia al elemento en caché en una variable local, se accede a la caché de datos directamente en la instrucción condicional y en Return. Supongamos que, cuando se alcanza este código, Cache("key") es distinto de Nothing, pero que antes de que se alcance la instrucción Return, el sistema expulsa key de la memoria caché. En este caso poco frecuente, el código devolverá Nothing, en lugar de un objeto del tipo esperado.

Nota:

La caché de datos es segura para los subprocesos, por lo que no es necesario sincronizar el acceso a subprocesos para lecturas o escrituras simples. Sin embargo, si necesita realizar varias operaciones en los datos de la caché que deben ser atómicas, es responsable de implementar un bloqueo o algún otro mecanismo para garantizar la seguridad de los subprocesos. Consulte Sincronizar el acceso a la caché de ASP.NET para obtener más información.

Un elemento se puede expulsar mediante programación de la caché de datos utilizando el métodoRemove de este modo:

Cache.Remove(key)

Paso 3: Devolver información del producto de la clase ProductsCL

En este tutorial, se implementarán dos métodos para devolver información del producto de la clase ProductsCL: GetProducts() y GetProductsByCategoryID(categoryID). Al igual que con la clase ProductsBL en la capa de lógica empresarial, el método GetProducts() de CL devuelve información sobre todos los productos como un objeto Northwind.ProductsDataTable, mientras que GetProductsByCategoryID(categoryID) devuelve todos los productos de una categoría especificada.

En el ejemplo de código siguiente, se muestra una parte de los métodos de la clase ProductsCL:

<System.ComponentModel.DataObject()> _
Public Class ProductsCL
    Private _productsAPI As ProductsBLL = Nothing
    Protected ReadOnly Property API() As ProductsBLL
        Get
            If _productsAPI Is Nothing Then
                _productsAPI = New ProductsBLL()
            End If
            Return _productsAPI
        End Get
    End Property
    <System.ComponentModel.DataObjectMethodAttribute _
    (DataObjectMethodType.Select, True)> _
    Public Function GetProducts() As Northwind.ProductsDataTable
        Const rawKey As String = "Products"
        ' See if the item is in the cache
        Dim products As Northwind.ProductsDataTable = _
            TryCast(GetCacheItem(rawKey), Northwind.ProductsDataTable)
        If products Is Nothing Then
            ' Item not found in cache - retrieve it and insert it into the cache
            products = API.GetProducts()
            AddCacheItem(rawKey, products)
        End If
        Return products
    End Function
    <System.ComponentModel.DataObjectMethodAttribute _
        (DataObjectMethodType.Select, False)> _
    Public Function GetProductsByCategoryID(ByVal categoryID As Integer) _
        As Northwind.ProductsDataTable
        If (categoryID < 0) Then
            Return GetProducts()
        Else
            Dim rawKey As String = String.Concat("ProductsByCategory-", categoryID)
            ' See if the item is in the cache
            Dim products As Northwind.ProductsDataTable = _
                TryCast(GetCacheItem(rawKey), Northwind.ProductsDataTable)
            If products Is Nothing Then
                ' Item not found in cache - retrieve it and insert it into the cache
                products = API.GetProductsByCategoryID(categoryID)
                AddCacheItem(rawKey, products)
            End If
            Return products
        End If
    End Function
End Class

En primer lugar, observe los atributos DataObjecty DataObjectMethodAttribute aplicados a la clase y los métodos. Estos atributos proporcionan información al asistente de ObjectDataSource, e indican qué clases y métodos deben aparecer en los pasos del asistente. Como se accederá a las clases y métodos de CL desde un ObjectDataSource en la capa de presentación, he añadido estos atributos para mejorar la experiencia en tiempo de diseño. Consulte el tutorial Creación de una capa de lógica empresarial para obtener una descripción más detallada de estos atributos y sus efectos.

En los métodos GetProducts() y GetProductsByCategoryID(categoryID), los datos devueltos desde el método GetCacheItem(key) se asignan a una variable local. El método GetCacheItem(key), que examinaremos en breve, devuelve un elemento determinado de la caché en función de la key especificada. Si no se encuentra ningún dato de este tipo en la caché, se recupera del método de clase ProductsBLL correspondiente y, a continuación, se añade a la caché utilizando el método AddCacheItem(key, value).

Los métodos GetCacheItem(key) y AddCacheItem(key, value) interactúan con la caché de datos, leyendo y escribiendo valores, respectivamente. El método GetCacheItem(key) es el más sencillo de los dos. Simplemente devuelve el valor de la clase Cache utilizando la key pasada:

Private Function GetCacheItem(ByVal rawKey As String) As Object
    Return HttpRuntime.Cache(GetCacheKey(rawKey))
End Function
Private ReadOnly MasterCacheKeyArray() As String = {"ProductsCache"}
Private Function GetCacheKey(ByVal cacheKey As String) As String
    Return String.Concat(MasterCacheKeyArray(0), "-", cacheKey)
End Function

GetCacheItem(key) no usa el valor de key tal como se proporciona, sino que llama al método GetCacheKey(key), que devuelve la key con el prefijo ProductsCache-. El método AddCacheItem(key, value) también utiliza MasterCacheKeyArray, que contiene la cadena ProductsCache, como veremos en breve.

A partir de una clase de código subyacente de la página ASP.NET, se puede acceder a la caché de datos utilizando la propiedad Cache de la clase Page, y se permite la sintaxis como Cache("key") = value, tal como se describe en el paso 2. A partir de una clase dentro de la arquitectura, se puede acceder a la caché de datos utilizando HttpRuntime.Cache o HttpContext.Current.Cache. La entrada de blog de Peter JohnsonHttpRuntime.Cache frente a HttpContext.Current.Cache señala la ligera ventaja de rendimiento en el uso de HttpRuntime en lugar de HttpContext.Current; en consecuencia, ProductsCL usa HttpRuntime.

Nota:

Si la arquitectura se implementa utilizando proyectos de la biblioteca de clases, deberá añadir una referencia al ensamblado System.Web para poder usar las clases HttpRuntime y HttpContext.

Si el elemento no se encuentra en la caché, los métodos de la clase ProductsCL obtienen los datos de BLL y los añaden a la caché utilizando el método AddCacheItem(key, value). Para añadir value a la caché, podemos usar el siguiente código, que utiliza una expiración de 60 segundos:

Const CacheDuration As Double = 60.0
Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
    DataCache.Insert(GetCacheKey(rawKey), value, Nothing, _
        DateTime.Now.AddSeconds(CacheDuration), _
        System.Web.Caching.Cache.NoSlidingExpiration)
End Sub

DateTime.Now.AddSeconds(CacheDuration) especifica una expiración basada en el tiempo de 60 segundos en el futuro, mientras que System.Web.Caching.Cache.NoSlidingExpiration indica que no hay ninguna expiración variable. Aunque esta sobrecarga de método Insert tiene parámetros de entrada para una expiración absoluta y una expiración variable, solo puede proporcionar uno de los dos. Si intenta especificar una hora absoluta y un intervalo de tiempo, el métodoInsert generará una excepción ArgumentException.

Nota:

Esta implementación del método AddCacheItem(key, value) actualmente tiene algunas deficiencias. Abordaremos y solucionaremos estos problemas en el paso 4.

Paso 4: Invalidación de la caché cuando los datos se modifican a través de la arquitectura

Junto con los métodos de recuperación de datos, la capa de caché debe proporcionar los mismos métodos que BLL para insertar, actualizar y eliminar datos. Los métodos de modificación de datos de la CL no modifican los datos en caché, sino que llaman al método de modificación de datos correspondiente de BLL y, a continuación, invalidan la caché. Como hemos visto en el tutorial anterior, este es el mismo comportamiento que aplica ObjectDataSource cuando se habilitan sus características de almacenamiento en caché y se invocan sus métodos Insert, Update o Delete.

La siguiente sobrecarga de UpdateProduct muestra cómo implementar los métodos de modificación de datos en la CL:

<DataObjectMethodAttribute(DataObjectMethodType.Update, False)> _
Public Function UpdateProduct(productName As String, _
    unitPrice As Nullable(Of Decimal), productID As Integer) _
    As Boolean
    Dim result As Boolean = API.UpdateProduct(productName, unitPrice, productID)
    ' TODO: Invalidate the cache
    Return result
End Function

Se invoca el método de capa de lógica empresarial de modificación de datos correspondiente, pero antes de que se devuelva su respuesta, es necesario invalidar la caché. Desafortunadamente, la invalidación de la caché no es sencilla, porque los métodos GetProducts() y GetProductsByCategoryID(categoryID) de la clase ProductsCL añaden elementos a la caché con claves diferentes, y el método GetProductsByCategoryID(categoryID) añade un elemento de caché diferente para cada categoryID exclusivo.

Al invalidar la caché, es necesario eliminar todos los elementos que haya añadido la clase ProductsCL. Esto se puede lograr asociando una dependencia de caché con cada elemento añadido a la caché en el método AddCacheItem(key, value). En general, una dependencia de caché puede ser otro elemento de la caché, un archivo del sistema de archivos, o datos de una base de datos de Microsoft SQL Server. Cuando la dependencia cambia o se elimina de la caché, los elementos de caché con los que está asociada se expulsan automáticamente de la caché. En este tutorial, queremos crear un elemento adicional en la caché que actúe como una dependencia de caché para todos los elementos añadidos a través de la clase ProductsCL. De este modo, todos estos elementos se pueden eliminar de la caché simplemente eliminando la dependencia de caché.

Vamos a actualizar el método AddCacheItem(key, value) para que cada elemento añadido a la caché a través de este método esté asociado con una sola dependencia de caché:

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), _
        System.Web.Caching.Cache.NoSlidingExpiration)
End Sub

MasterCacheKeyArray es una matriz de cadenas que contiene un valor único, ProductsCache. En primer lugar, se añade un elemento de caché a la caché y se le asigna la fecha y la hora actuales. Si el elemento de caché ya existe, se actualiza. A continuación, se crea una dependencia de caché. El constructor de la clase CacheDependency tiene varias sobrecargas, pero la que se usa aquí espera dos entradas de matriz de String. La primera especifica el conjunto de archivos que se van a usar como dependencias. Como no queremos usar ninguna dependencia basada en archivos, se utiliza un valor de Nothing para el primer parámetro de entrada. El segundo parámetro de entrada especifica el conjunto de claves de caché que se van a usar como dependencias. Aquí especificamos nuestra única dependencia, MasterCacheKeyArray. A continuación, se pasa CacheDependency al método Insert.

Con esta modificación en AddCacheItem(key, value), invalidar la caché es tan sencillo como eliminar la dependencia.

<DataObjectMethodAttribute(DataObjectMethodType.Update, False)> _
Public Function UpdateProduct(ByVal productName As String, _
    ByVal unitPrice As Nullable(Of Decimal), ByVal productID As Integer) _
    As Boolean
    Dim result As Boolean = API.UpdateProduct(productName, unitPrice, productID)
    ' Invalidate the cache
    InvalidateCache()
    Return result
End Function
Public Sub InvalidateCache()
    ' Remove the cache dependency
    HttpRuntime.Cache.Remove(MasterCacheKeyArray(0))
End Sub

Paso 5: Llamar a la capa de caché desde la capa de presentación

Las clases y métodos de la capa de caché se pueden usar para trabajar con datos utilizando las técnicas que hemos examinado en estos tutoriales. Para ilustrar cómo trabajar con datos en caché, guarde los cambios en la clase ProductsCL y, a continuación, abra la página FromTheArchitecture.aspx en la carpeta Caching y añada una GridView. En la etiqueta inteligente de GridView, cree un nuevo ObjectDataSource. En el primer paso del asistente, debería ver la clase ProductsCL como una de las opciones de la lista desplegable.

The ProductsCL Class is Included in the Business Object Drop-Down List

Figura 4: La clase ProductsCL se incluye en la lista desplegable de objetos de negocio (haga clic aquí para ver la imagen a tamaño completo)

Después de seleccionar ProductsCL, haga clic en Siguiente. La lista desplegable de la pestaña SELECT tiene dos elementos: GetProducts() y GetProductsByCategoryID(categoryID), y la pestaña UPDATE tiene la única sobrecarga de UpdateProduct. Elija el método GetProducts() en la pestaña SELECT y el método UpdateProducts en la pestaña UPDATE, y haga clic en Finalizar.

The ProductsCL Class s Methods are Listed in the Drop-Down Lists

Figura 5: Los métodos de la clase ProductsCL se enumeran en las listas desplegables (haga clic aquí para ver la imagen a tamaño completo)

Después de completar el asistente, Visual Studio establecerá la propiedad OldValuesParameterFormatString de ObjectDataSource en original_{0} y añadirá los campos adecuados a GridView. Vuelva a cambiar la propiedad OldValuesParameterFormatString a su valor predeterminado, {0}, y configure GridView para admitir la paginación, la ordenación y la edición. Puesto que la sobrecarga de UploadProducts usada por la CL solo acepta el nombre y el precio del producto editado, limite GridView para que solo se puedan editar estos campos.

En el tutorial anterior, hemos definido una GridView para incluir campos para los campos ProductName, CategoryName y UnitPrice. No dude en replicar este formato y esta estructura, en cuyo caso los marcados declarativos de GridView y ObjectDataSource deben tener un aspecto similar al siguiente:

<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
    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") %>'></asp:Label>
            </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="ProductsDataSource" 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>

En este punto, tenemos una página que usa la capa de caché. Para ver la caché en acción, establezca puntos de interrupción en los métodos GetProducts() y UpdateProduct de la clase ProductsCL. Visite la página en un explorador y recorra el código durante la ordenación y la paginación para ver los datos extraídos de la caché. A continuación, actualice un registro y observe que la caché se invalida y, por lo tanto, se recupera de BLL cuando los datos se vuelven a enlazar con GridView.

Nota:

La capa de caché proporcionada en la descarga que acompaña a este artículo no está completa. Solo contiene una clase, ProductsCL, que solo tiene unos pocos métodos. Asimismo, solo una página ASP.NET usa la CL(~/Caching/FromTheArchitecture.aspx); las demás siguen haciendo referencia directamente a BLL. Si tiene previsto usar una CL en la aplicación, todas las llamadas provenientes de la capa de presentación deben ir a la CL, lo que requerirá que las clases y métodos de la CL cubran esas clases y métodos en el BLL que usa actualmente la capa de presentación.

Resumen

Aunque el almacenamiento en caché se puede aplicar en la capa de presentación con los controles SqlDataSource y ObjectDataSource de ASP.NET 2.0, idealmente las responsabilidades de almacenamiento en caché se delegarán a una capa independiente en la arquitectura. En este tutorial, hemos creado una capa de caché que reside entre la capa de presentación y la capa de lógica empresarial. La capa de caché debe proporcionar el mismo conjunto de clases y métodos que existen en el BLL y se llaman desde la capa de presentación.

Los ejemplos de capa de caché que hemos explorado en este y en los tutoriales anteriores mostraron una carga reactiva. Con la carga reactiva, los datos solo se cargan en la caché cuando se realiza una solicitud de datos y esos datos faltan en la caché. Los datos también se pueden cargar proactivamente en la caché, una técnica que carga los datos en la caché antes de que sean realmente necesarios. En el siguiente tutorial, veremos un ejemplo de carga proactiva cuando queremos almacenar valores estáticos en la caché durante el inicio de la aplicación.

¡Feliz programación!

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, instructor y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Puede ponerse en contacto con él en mitchell@4GuysFromRolla.com. o a través de su blog, http://ScottOnWriting.NET.

Agradecimientos especiales a

Muchos revisores han evaluado esta serie de tutoriales. El revisor principal de este tutorial ha sido Teresa Murphy. ¿Le interesa revisar mis próximos artículos de MSDN? Si es así, escríbame a mitchell@4GuysFromRolla.com.