Compartilhar via


Armazenar dados em cache na arquitetura (VB)

por Scott Mitchell

Baixar PDF

No tutorial anterior, aprendemos a aplicar o cache na Camada de Apresentação. Neste tutorial, aprendemos a aproveitar nossa arquitetura em camadas para armazenar dados em cache na Camada Lógica de Negócios. Fazemos isso estendendo a arquitetura para incluir uma Camada de Cache.

Introdução

Como vimos no tutorial anterior, armazenar em cache os dados do ObjectDataSource é tão simples quanto definir algumas propriedades. Infelizmente, o ObjectDataSource aplica o cache na Camada de Apresentação, que associa firmemente as políticas de cache com a página ASP.NET. Uma das razões para criar uma arquitetura em camadas é permitir que esses acoplamentos sejam quebrados. A Camada de Lógica de Negócios, por exemplo, separa a lógica de negócios das páginas ASP.NET, enquanto a Camada de Acesso a Dados separa os detalhes de acesso a dados. Essa desacoplamento da lógica de negócios e dos detalhes de acesso a dados é preferencial, em parte, porque torna o sistema mais legível, mais mantenedível e mais flexível para alterar. Ele também permite o conhecimento de domínio e a divisão do trabalho que um desenvolvedor que trabalha na Camada de Apresentação não precisa estar familiarizado com os detalhes do banco de dados para fazer seu trabalho. A desacoplamento da política de cache da Camada de Apresentação oferece benefícios semelhantes.

Neste tutorial, aumentaremos nossa arquitetura para incluir uma camada de cache (ou CL) que emprega nossa política de cache. A Camada de Cache incluirá uma ProductsCL classe que fornece acesso às informações do produto com métodos como GetProducts(), GetProductsByCategoryID(categoryID)e assim por diante, que, quando invocado, tentará primeiro recuperar os dados do cache. Se o cache estiver vazio, esses métodos invocarão o método apropriado ProductsBLL na BLL, que, por sua vez, obteria os dados do DAL. Os ProductsCL métodos armazenam em cache os dados recuperados da BLL antes de devolvê-los.

Como mostra a Figura 1, o CL reside entre as Camadas de Lógica de Apresentação e Negócios.

A CL (Camada de Cache) é outra camada em nossa arquitetura

Figura 1: a CL (camada de cache) é outra camada em nossa arquitetura

Etapa 1: Criando as classes de camada de cache

Neste tutorial, criaremos um CL muito simples com uma única classe ProductsCL que tem apenas um punhado de métodos. A criação de uma camada de cache completa para todo o aplicativo exigiria a criação CategoriesCLde classes , EmployeesCLe SuppliersCL e e o fornecimento de um método nessas classes de Camada de Cache para cada método de acesso ou modificação de dados na BLL. Assim como acontece com a BLL e a DAL, a Camada de Cache deve ser implementada idealmente como um projeto separado da Biblioteca de Classes; no entanto, vamos implementá-lo como uma classe na App_Code pasta .

Para separar de forma mais limpa as classes CL das classes DAL e BLL, vamos criar uma nova subpasta na App_Code pasta . Clique com o botão direito do App_Code mouse na pasta no Gerenciador de Soluções, escolha Nova Pasta e nomeie a nova pasta CL. Depois de criar essa pasta, adicione a ela uma nova classe chamada ProductsCL.vb.

Adicionar uma nova pasta chamada CL e uma classe chamada ProductsCL.vb

Figura 2: Adicionar uma nova pasta chamada CL e uma classe nomeada ProductsCL.vb

A ProductsCL classe deve incluir o mesmo conjunto de métodos de acesso e modificação de dados, conforme encontrado em sua classe de Camada de Lógica De Negócios correspondente (ProductsBLL). Em vez de criar todos esses métodos, vamos apenas criar um par aqui para ter uma ideia dos padrões usados pelo CL. Em particular, adicionaremos os GetProducts() métodos e GetProductsByCategoryID(categoryID) na Etapa 3 e uma UpdateProduct sobrecarga na Etapa 4. Você pode adicionar os métodos restantes ProductsCL e CategoriesCLas classes , EmployeesCLe SuppliersCL no seu lazer.

Etapa 2: Leitura e gravação no Cache de Dados

O recurso de cache ObjectDataSource explorado no tutorial anterior usa internamente o cache de dados ASP.NET para armazenar os dados recuperados da BLL. O cache de dados também pode ser acessado programaticamente de ASP.NET páginas de classes code-behind ou das classes na arquitetura do aplicativo Web. Para ler e gravar no cache de dados de uma classe code-behind de uma página ASP.NET, use o seguinte padrão:

' 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)

O Cache método de classe s Insert tem várias sobrecargas. Cache("key") = value e Cache.Insert(key, value) são sinônimos e adicionam um item ao cache usando a chave especificada sem uma expiração definida. Normalmente, queremos especificar uma expiração ao adicionar um item ao cache, seja como uma dependência, uma expiração baseada em tempo ou ambas. Use uma das sobrecargas de outro Insert método para fornecer informações de expiração baseadas em dependência ou tempo.

Os métodos da Camada de Cache precisam primeiro marcar se os dados solicitados estiverem no cache e, nesse caso, devolvê-los de lá. Se os dados solicitados não estiverem no cache, o método BLL apropriado precisará ser invocado. Seu valor retornado deve ser armazenado em cache e retornado, como ilustra o diagrama de sequência a seguir.

Os métodos da camada de cache retornam dados do cache se estiverem disponíveis

Figura 3: os métodos da camada de cache retornam dados do cache se estiverem disponíveis

A sequência descrita na Figura 3 é realizada nas classes CL usando o seguinte padrão:

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

Aqui, Type é o tipo de dados que está sendo armazenado no cache Northwind.ProductsDataTable, por exemplo, enquanto key é a chave que identifica exclusivamente o item de cache. Se o item com a chave especificada não estiver no cache, a instância será Nothing e os dados serão recuperados do método BLL apropriado e adicionados ao cache. Quando é atingido, a Return instanceinstância contém uma referência aos dados, seja do cache ou extraída da BLL.

Certifique-se de usar o padrão acima ao acessar dados do cache. O padrão a seguir, que, à primeira vista, parece equivalente, contém uma diferença sutil que introduz uma condição de corrida. As condições de corrida são difíceis de depurar porque se revelam esporadicamente e são difíceis de reproduzir.

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

A diferença neste segundo snippet de código incorreto é que, em vez de armazenar uma referência ao item armazenado em cache em uma variável local, o cache de dados é acessado diretamente na instrução condicional e no Return. Imagine que, quando esse código for atingido, Cache("key") não Nothingé , mas antes que a Return instrução seja atingida, o sistema remove a chave do cache. Nesse caso raro, o código retornará Nothing em vez de um objeto do tipo esperado.

Observação

O cache de dados é thread-safe, portanto, você não precisa sincronizar o acesso de thread para leituras ou gravações simples. No entanto, se você precisar executar várias operações em dados no cache que precisam ser atômicos, será responsável por implementar um bloqueio ou algum outro mecanismo para garantir a segurança do thread. Consulte Sincronizando o acesso ao cache ASP.NET para obter mais informações.

Um item pode ser removido programaticamente do cache de dados usando o Remove método assim:

Cache.Remove(key)

Etapa 3: Retornando informações do produto daProductsCLclasse

Para este tutorial, vamos implementar dois métodos para retornar informações do produto da ProductsCL classe : GetProducts() e GetProductsByCategoryID(categoryID). Assim como acontece com a ProductsBL classe na Camada de Lógica de Negócios, o GetProducts() método no CL retorna informações sobre todos os produtos como um Northwind.ProductsDataTable objeto, enquanto GetProductsByCategoryID(categoryID) retorna todos os produtos de uma categoria especificada.

O código a seguir mostra uma parte dos métodos na ProductsCL classe :

<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

Primeiro, observe os DataObject atributos e DataObjectMethodAttribute aplicados à classe e aos métodos. Esses atributos fornecem informações para o assistente objectDataSource, indicando quais classes e métodos devem aparecer nas etapas do assistente. Como as classes e os métodos CL serão acessados de um ObjectDataSource na Camada de Apresentação, aditei esses atributos para aprimorar a experiência de tempo de design. Consulte o tutorial Criando uma camada lógica de negócios para obter uma descrição mais completa sobre esses atributos e seus efeitos.

GetProducts() Nos métodos e GetProductsByCategoryID(categoryID) , os dados retornados do GetCacheItem(key) método são atribuídos a uma variável local. O GetCacheItem(key) método, que examinaremos em breve, retorna um item específico do cache com base na chave especificada. Se esses dados não forem encontrados no cache, eles serão recuperados do método de classe correspondente ProductsBLL e adicionados ao cache usando o AddCacheItem(key, value) método .

A GetCacheItem(key) interface dos métodos e AddCacheItem(key, value) com o cache de dados, os valores de leitura e gravação, respectivamente. O GetCacheItem(key) método é o mais simples dos dois. Ele simplesmente retorna o valor da classe Cache usando a chave passada:

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) não usa o valor da chave conforme fornecido, mas chama o GetCacheKey(key) método , que retorna a chave pré-acrescentada com ProductsCache-. O MasterCacheKeyArray, que contém a cadeia de caracteres ProductsCache, também é usado pelo AddCacheItem(key, value) método , como veremos momentaneamente.

Em uma classe code-behind de página ASP.NET, o cache de dados pode ser acessado usando a Page propriedade da Cacheclasse e permite a sintaxe como Cache("key") = value, conforme discutido na Etapa 2. De uma classe dentro da arquitetura, o cache de dados pode ser acessado usando HttpRuntime.Cache ou HttpContext.Current.Cache. A entrada de blog de Peter JohnsonHttpRuntime.Cache vs. HttpContext.Current.Cache observa a pequena vantagem de desempenho em usar HttpRuntime em vez de HttpContext.Current; consequentemente, ProductsCL usa HttpRuntime.

Observação

Se sua arquitetura for implementada usando projetos da Biblioteca de Classes, você precisará adicionar uma referência ao System.Web assembly para usar as HttpRuntime classes e HttpContext .

Se o item não for encontrado no cache, os ProductsCL métodos da classe obterão os dados da BLL e os adicionarão ao cache usando o AddCacheItem(key, value) método . Para adicionar valor ao cache, poderíamos usar o seguinte código, que usa uma expiração 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 a expiração baseada em tempo de 60 segundos no futuro, enquanto System.Web.Caching.Cache.NoSlidingExpiration indica que não há expiração deslizante. Embora essa sobrecarga de Insert método tenha parâmetros de entrada para uma expiração absoluta e deslizante, você só pode fornecer um dos dois. Se você tentar especificar um tempo absoluto e um intervalo de tempo, o Insert método gerará uma exceção ArgumentException .

Observação

Essa implementação do AddCacheItem(key, value) método atualmente tem algumas deficiências. Abordaremos e superaremos esses problemas na Etapa 4.

Etapa 4: Invalidando o cache quando os dados são modificados por meio da arquitetura

Juntamente com os métodos de recuperação de dados, a Camada de Cache precisa fornecer os mesmos métodos que a BLL para inserir, atualizar e excluir dados. Os métodos de modificação de dados de CL não modificam os dados armazenados em cache, mas chamam o método de modificação de dados correspondente da BLL e invalidam o cache. Como vimos no tutorial anterior, esse é o mesmo comportamento que o ObjectDataSource aplica quando seus recursos de cache são habilitados e seus Insertmétodos , Updateou Delete são invocados.

A sobrecarga a seguir UpdateProduct ilustra como implementar os métodos de modificação de dados no 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

O método de camada de lógica de negócios de modificação de dados apropriado é invocado, mas antes que sua resposta seja retornada, precisamos invalidar o cache. Infelizmente, invalidar o cache não é simples porque a classe s GetProducts() e GetProductsByCategoryID(categoryID) os ProductsCL métodos adicionam itens ao cache com chaves diferentes e o GetProductsByCategoryID(categoryID) método adiciona um item de cache diferente para cada categoryID exclusivo.

Ao invalidar o cache, precisamos remover todos os itens que podem ter sido adicionados pela ProductsCL classe . Isso pode ser feito associando uma dependência de cache a cada item adicionado ao cache no AddCacheItem(key, value) método . Em geral, uma dependência de cache pode ser outro item no cache, um arquivo no sistema de arquivos ou dados de um banco de dados do Microsoft SQL Server. Quando a dependência é alterada ou removida do cache, os itens de cache aos quais ele está associado são removidos automaticamente do cache. Para este tutorial, queremos criar um item adicional no cache que serve como uma dependência de cache para todos os itens adicionados por meio da ProductsCL classe . Dessa forma, todos esses itens podem ser removidos do cache simplesmente removendo a dependência de cache.

Vamos atualizar o AddCacheItem(key, value) método para que cada item adicionado ao cache por meio desse método seja associado a uma única dependência de cache:

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 é uma matriz de cadeia de caracteres que contém um único valor, ProductsCache. Primeiro, um item de cache é adicionado ao cache e atribuído à data e hora atuais. Se o item de cache já existir, ele será atualizado. Em seguida, uma dependência de cache é criada. O CacheDependency construtor da classe s tem várias sobrecargas, mas o que está sendo usado aqui espera duas String entradas de matriz. O primeiro especifica o conjunto de arquivos a serem usados como dependências. Como não queremos usar nenhuma dependência baseada em arquivo, um valor de Nothing é usado para o primeiro parâmetro de entrada. O segundo parâmetro de entrada especifica o conjunto de chaves de cache a serem usadas como dependências. Aqui, especificamos nossa dependência única, MasterCacheKeyArray. Em CacheDependency seguida, o é passado para o Insert método .

Com essa modificação em AddCacheItem(key, value), invalidar o cache é tão simples quanto remover a dependência.

<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

Etapa 5: Chamando a camada de cache da camada de apresentação

As classes e os métodos da Camada de Cache podem ser usados para trabalhar com dados usando as técnicas que examinamos ao longo desses tutoriais. Para ilustrar o trabalho com dados armazenados em cache, salve suas alterações na ProductsCL classe e abra a FromTheArchitecture.aspx página na Caching pasta e adicione um GridView. Na marca inteligente gridView, crie um novo ObjectDataSource. Na primeira etapa do assistente, você deve ver a ProductsCL classe como uma das opções da lista suspensa.

A classe ProductsCL está incluída na lista de Drop-Down de objetos corporativos

Figura 4: a ProductsCL classe está incluída na lista de Drop-Down de objetos corporativos (clique para exibir a imagem em tamanho real)

Depois de ProductsCLselecionar , clique em Avançar. A lista suspensa na guia SELECT tem dois itens e GetProducts()GetProductsByCategoryID(categoryID) a guia UPDATE tem a única UpdateProduct sobrecarga. Escolha o GetProducts() método na guia SELECT e o UpdateProducts método na guia UPDATE e clique em Concluir.

Os métodos da classe ProductsCL são listados no Drop-Down Listas

Figura 5: Os ProductsCL métodos da classe são listados no Drop-Down Listas (clique para exibir a imagem em tamanho real)

Depois de concluir o assistente, o Visual Studio definirá a propriedade original_{0} objectDataSource como OldValuesParameterFormatString e adicionará os campos apropriados ao GridView. Altere a OldValuesParameterFormatString propriedade de volta para seu valor padrão, {0}e configure o GridView para dar suporte à paginação, classificação e edição. Como a UploadProducts sobrecarga usada pela CL aceita apenas o nome e o preço do produto editado, limite o GridView para que apenas esses campos sejam editáveis.

No tutorial anterior, definimos um GridView para incluir campos para os ProductNamecampos , CategoryNamee UnitPrice . Fique à vontade para replicar essa formatação e estrutura; nesse caso, a marcação declarativa de GridView e ObjectDataSource deve ser semelhante à seguinte:

<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>

Neste ponto, temos uma página que usa a Camada de Cache. Para ver o cache em ação, defina pontos de interrupção nas ProductsCL classes s GetProducts() e UpdateProduct métodos. Visite a página em um navegador e percorra o código ao classificar e paginar para ver os dados extraídos do cache. Em seguida, atualize um registro e observe que o cache é invalidado e, consequentemente, ele é recuperado da BLL quando os dados são recuperados para o GridView.

Observação

A Camada de Cache fornecida no download que acompanha este artigo não está concluída. Ele contém apenas uma classe, ProductsCL, que só ostenta um punhado de métodos. Além disso, apenas uma única página ASP.NET usa a CL (~/Caching/FromTheArchitecture.aspx) todas as outras ainda referenciam a BLL diretamente. Se você planeja usar uma CL em seu aplicativo, todas as chamadas da Camada de Apresentação devem ir para a CL, o que exigiria que as classes e métodos cl s abordassem essas classes e métodos na BLL atualmente usada pela Camada de Apresentação.

Resumo

Embora o cache possa ser aplicado na Camada de Apresentação com os controles SqlDataSource e ObjectDataSource do ASP.NET 2.0, o ideal é que as responsabilidades de cache sejam delegadas a uma camada separada na arquitetura. Neste tutorial, criamos uma Camada de Cache que reside entre a Camada de Apresentação e a Camada lógica de negócios. A Camada de Cache precisa fornecer o mesmo conjunto de classes e métodos que existem na BLL e são chamados da Camada de Apresentação.

Os exemplos da Camada de Cache que exploramos neste e nos tutoriais anteriores exibiram o carregamento reativo. Com o carregamento reativo, os dados são carregados no cache somente quando uma solicitação para os dados é feita e esses dados estão ausentes do cache. Os dados também podem ser carregados proativamente no cache, uma técnica que carrega os dados no cache antes que eles sejam realmente necessários. No próximo tutorial, veremos um exemplo de carregamento proativo quando examinarmos como armazenar valores estáticos no cache na inicialização do aplicativo.

Programação feliz!

Sobre o autor

Scott Mitchell, autor de sete livros do ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Microsoft Web desde 1998. Scott trabalha como consultor independente, treinador e escritor. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 Horas. Ele pode ser contatado em mitchell@4GuysFromRolla.com. ou através de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.

Agradecimentos Especiais

Esta série de tutoriais foi revisada por muitos revisores úteis. A revisora principal deste tutorial foi Teresa Murphy. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, deixe-me uma linha em mitchell@4GuysFromRolla.com.