Almacenamiento en caché de datos en Web API


Tengo la necesidad de almacenar en caché una colección de objetos que es en su mayoría estática (podría tener cambios 1x por día) que está disponible en mi ASP.NET Servicio Web API OData. Este conjunto de resultados se usa entre llamadas (lo que significa que no es específico de la llamada del cliente), por lo que debe almacenarse en caché a nivel de aplicación.

Hice un montón de búsquedas en 'almacenamiento en caché en Web API', pero todos los resultados fueron sobre 'almacenamiento en caché de salida'. Eso no es lo que estoy buscando aquí. Quiero almacenar en caché una colección' People ' para ser reutilizada llamadas posteriores (pueden tener un vencimiento deslizante).

Mi pregunta es, ya que esto todavía es justo ASP.NET, ¿utilizo técnicas tradicionales de almacenamiento en caché de aplicaciones para persistir esta colección en la memoria, o hay algo más que tengo que hacer? Esta colección no se devuelve directamente al usuario, sino que se utiliza como fuente detrás de escena para consultas OData a través de llamadas a la API. No hay razón para que vaya a la base de datos en cada llamada para obtener el exacto mismo información sobre cada llamada. Expirarlo cada hora debería ser suficiente.

¿Alguien sabe cómo almacenar correctamente los datos en caché en este escenario?

Author: atconway, 2013-05-08

2 answers

Sí, el almacenamiento en caché de salida no es lo que está buscando. Puede almacenar en caché los datos en memoria con MemoryCache, por ejemplo, http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx . Sin embargo, perderá esos datos si el grupo de aplicaciones se recicla. Otra opción es usar una caché distribuida como AppFabric Cache o MemCache, por nombrar algunas.

 25
Author: Pablo Cibraro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-08 17:04:54

La solución que terminé usando involucró MemoryCache en el espacio de nombres System.Runtime.Caching. Aquí está el código que terminó funcionando para almacenar en caché mi colección:

//If the data exists in cache, pull it from there, otherwise make a call to database to get the data
ObjectCache cache = MemoryCache.Default;

var peopleData = cache.Get("PeopleData") as List<People>;
if (peopleData != null)
   return peopleData ;

peopleData = GetAllPeople();
CacheItemPolicy policy = new CacheItemPolicy {AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(30)};
cache.Add("PeopleData", peopleData, policy);
return peopleData;

Aquí hay otra forma que encontré usando Lazy<T> para tener en cuenta el bloqueo y la concurrencia. El crédito total va a esta publicación: ¿Cómo lidiar con costosas operaciones de construcción usando MemoryCache?

private IEnumerable<TEntity> GetFromCache<TEntity>(string key, Func<IEnumerable<TEntity>> valueFactory) where TEntity : class 
{
    ObjectCache cache = MemoryCache.Default;
    var newValue = new Lazy<IEnumerable<TEntity>>(valueFactory);            
    CacheItemPolicy policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(30) };
    //The line below returns existing item or adds the new value if it doesn't exist
    var value = cache.AddOrGetExisting(key, newValue, policy) as Lazy<IEnumerable<TEntity>>;
    return (value ?? newValue).Value; // Lazy<T> handles the locking itself
}
 37
Author: atconway,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:33