O objetivo 1.2 do exame 70-487: Developing Microsoft Azure and Web Services, Implement caching, trata-se de implementações de cache. Nesse objetivo, é necessário que você se familiarize com dois objetos de cache: ObjectCache e o HttpContext.Cache.
ObjectCache
O ObjectCache provê a funcionalidade de cache com extrema facilidade. Basta obter a instância dele usando MemoryCache.Default e usar os métodos que têm nomes amigáveis como Add, AddOrGetExisting, Get e Set. Pode não ser fácil memorizar todos os overloads, mas já chegamos lá. Primeiro dê uma olhada num uso simples do ObjectCache:
Note que é necessário primeiro remover o item do cache antes de chamar o método Add. Isso ocorre porque internamente o método Add usa o método AddOrGetExisting, então ele não substitui o valor anterior. Para obter um valor, você pode usar o método Get ou chamar diretamente o indexador (cache[key]).
Vamos às diferentes formas de adicionar um item no cache:
- Add(CacheItem, CacheItemPolicy)
- Add(String key, Object value, DateTimeOffset absoluteExpiration)
- Add(String key, Object value, CacheItemPolicy policy, String regionName)
- AddOrGetExisting(CacheItem, CacheItemPolicy)
- AddOrGetExisting(String key, Object value, DateTimeOffset absoluteExpiration)
- AddOrGetExisting(String key, Object value, CacheItemPolicy policy, String regionName)
- Set(CacheItem, CacheItemPolicy)
- Set(String key, Object value, CacheItemPolicy policy, String regionName)
Embora numerosos, esses overloads são bem parecidos. Certifique-se de memorizá-los.
O efeito de todos eles é bem parecido. A principal diferença é que o método Add, por internamente usar o método AddOrGetExisting, retorna um bool indicando se o item foi inserido no cache ou se ele já existia. Já o método Set não tem retorno e atualiza o valor se o item já estiver no cache.
O objeto CacheItem tem três propriedades: Key, Value e RegionName.
No objeto CacheItemPolicy, você pode setar a política de expiração usando a propriedade AbsoluteExpiration ou a SlidingExpiration. A diferença entre as duas é que, com AbsoluteExpiration, você determina exatamente a data em que o item vai ser removido do cache. Já com SlidingExpiration, o item é removido do cache se não for utilizado após o tempo (TimeSpan) determinado.
Ainda no CacheItemPolicy, você pode configurar também a propriedade Priority com o enum CacheItemPriority. No System.Runtime.Caching (ObjectCache), ele tem dois possíveis valores: Default (que é o marcado por padrão) e NotRemovable. A propriedade Priority funciona assim: quando os recursos de processamento estão baixos, o runtime pode limpar algumas coisas da memória para melhorar o processamento. Os itens do cache estão incluídos nessa limpeza. Esse é o comportamento padrão, adotado quando a Priority está com o valor Default. Os itens do cache adicionados com o valor NotRemovable na propriedade Prority nunca são removidos do cache pelo runtime. Isso é perigoso pois a aplicação pode crashar devido à falta de memória.
O objeto CacheItemPolicy conta ainda com uma lista de ChangeMonitor. Esse objeto, como o nome sugere, lida com mudanças (eventos) que causam atualização do cache. ChangeMonitor é uma classe base que tem várias implementações:
- CacheEntryChangeMonitor: serve como base para a construção de classes derivadas que monitoram os CacheItems
- FileChangeMonitor: monitora um arquivo checando se há mudanças para atualizar o cache
- HostFileChangeMonitor: monitora mudanças em diretórios e caminhos de arquivos, como o nome ou tamanho de um arquivo.
HttpContext.Cache
O HttpContext.Cache foi criado para ser usado especificamente numa aplicação web ASP.NET (fica em System.Web.Caching). Tome cuidado para não confundir os dois no exame. Se alguma questão mencionar o objeto HttpContext.Cache, Page.Cache ou somente Cache, você deve assumir que se trata de uma aplicação ASP.NET. Quaisquer outras menções à cache, pode se assumir que se trata do ObjectCache.
O jeito mais simples de adicionar ou atualizar um item no HttpContext.Cache é assim: Cache["FullNameKey"] = "John Q. Public";
. Há também os métodos Add e Insert, que contêm várias sobrecargas (e infelizmente você também deve memorizar todas elas):
- Insert(String Key, Object Value)
- Insert(String Key, Object Value, CacheDependency dependencyItem)
- Insert(String Key, Object Value, CacheDependency dependencyItem, DateTime absoluteExpiration, TimeSpan slidingExpiration)
- Insert(String Key, Object Value, CacheDependency dependencyItem, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback updateCallback)
- Insert(String Key, Object Value, CacheDependency dependencyItem, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback removeCallback)
- Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
O método Add e a última forma do método Insert são virtualmente idênticos. A principal diferença está no método Insert que usa um CacheItemUpdateCallback, ao contrário do método Add que usa um CacheItemRemovedCallback. Em RemoveCallback é chamado quando o item é removido do cache, enquanto UpdateCallback é invocado um pouco antes do item ser removido do cache. Para a maioria das aplicações isso não faz muita diferença, mas a ideia é que se você precisa se certificar que um item nunca seja removido do cache, por exemplo, use UpdateCallback.
Assim como no ObjectCache, temos aqui também o enum CacheItemPriority, que funciona da mesma forma. A diferença é que aqui há mais opções de valores, com nomes bem sugestivos: Low, BelowNormal, Normal, AboveNormal, High, NotRemovable e Default. O valor padrão é Normal, que funciona da mesma forma que Default.
Para finalizar, há o parâmetro CacheDependency, que lida com cache de arquivos (como o HostFileChangeMonitor). Você pode passar também um objeto bem importante, o SqlCacheDependency. Ele tem dois construtores: um que aceita um SqlCommand e outro que aceita duas strings, a primeira sendo o nome do banco definido no web.config e a segunda é o nome da tabela que o cache será associado. Há muitos requisitos para se usar SqlCacheDependency, e alguns cuidados devem ser tomados.
Para o primeiro construtor, o banco de dados deve ser SQL Server 2005 ou superior. Dentro do SqlCommand, as tabelas devem ser referenciadas com o owner (dbo.Customer, por exemplo). SELECT * é proibido e a página não pode ter output caching.
O segundo é ainda mais complicado. Deve haver uma connection string no web.config da aplicação (obviamente). O banco de dados e a tabela devem ter notificações habilitadas no SQL Server e não é possível associar o cache com mais de uma tabela.
E é isso. O conteúdo desse objetivo foi bem simples, apesar de ser difícil decorar todos os overloads dos métodos de inserção.
Nos vemos no post do próximo objetivo, Implement transactions.
Até mais!