Quando sfruttiamo la cache di ASP.NET per limitare gli accessi alla base dati, tipicamente siamo sempre costretti, in maniera ripetitiva, a verificare la presenza dell'oggetto desiderato in cache ed eventualmente recuperarlo dal database, come nel codice seguente:
public List<Customer> GetCustomers()
{
List<Customer> result = this.Cache["customers.all"] as List<Customer>;
if (result == null)
{
// codice per recuperare i customers da database
result = CustomerRepository.GetAllCustomers();
Cache.Insert("customers.all", result);
}
return result;
}
Una soluzione sicuramente più pulita, dal punto di vista architetturale, è quella di realizzare una classe helper che incapsuli la logica di gestione della cache. In particolare, potremmo implementare un metodo generico GetItem che, sfruttando generics e delegate, ci consenta di gestire l'operazione vista in precedenza con un'unica chiamata:
public static class CacheHelper
{
public static T GetItem<T>(string key, Func<T> fetchDelegate) where T:class
{
ObjectCache cache = MemoryCache.Default;
var result = (T)cache[key];
if (result != null)
return result;
// oggetto non trovato, recuperiamolo tramite il delegate
result = fetchDelegate();
if (result != null)
{
// aggiungiamo l'oggetto appena recuperato in cache,
// con un timeout di 5 minuti
cache.Add(key, result,
new CacheItemPolicy() { AbsoluteExpiration = DateTime.Now.AddMinutes(5) });
}
return result;
}
}
Il metodo GetItem accetta una chiave di cache e un delegate, di tipo Func<T>, che viene invocato all'occorrenza, per recuperare l'oggetto desiderato nel caso non sia presente in cache. Come possiamo notare, tra l'altro, abbiamo anche sfruttato le nuove API di caching del .Net Framework 4, utilizzando la classe astratta ObjectCache. Questo approccio ci consente, all'occorrenza, di migrare verso altri engine (ad esempio un server di cache distribuita come AppFabric), minimizzando gli impatti sul codice. Un ulteriore vantaggio di ObjectCache è che è completamente stand-alone e slegato dall'HttpContext, pertanto possiamo sfruttare CacheHelper anche in applicazioni che non siano necessariamente Web, come ad esempio un Web Service realizzato con WCF.
Grazie anche alla type inference dei generics e alla sinteticità delle lambda expression, il codice che dobbiamo scrivere nel nostro metodo GetCustomers diviene davvero molto semplice:
public List<Customer> GetCustomers()
{
return CacheHelper.GetItem("customers.all", () =>
{
return CustomerRepository.GetAllCustomers();
});
}
In un prossimo script, vedremo come migliorare ulteriormente CacheHelper per gestire, ad esempio, diverse policy a seconda del tipo di risultato desiderato.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Eseguire script pre e post esecuzione di un workflow di GitHub
Utilizzare l nesting nativo dei CSS
Rinnovare il token di una GitHub App durante l'esecuzione di un workflow
Implementare l'infinite scroll con QuickGrid in Blazor Server
Gestire eccezioni nei plugin di Semantic Kernel in ASP.NET Core Web API
Selettore CSS :has() e i suoi casi d'uso avanzati
Ricevere notifiche sui test con Azure Load Testing
Utilizzare il nuovo modello GPT-4o con Azure OpenAI
Utilizzare il metodo ExceptBy per eseguire operazione di sottrazione tra liste
Utilizzare la funzione EF.Parameter per forzare la parametrizzazione di una costante con Entity Framework
Utilizzare il metodo Index di LINQ per scorrere una lista sapendo anche l'indice dell'elemento
Utilizzare il trigger SQL con le Azure Function