Кэширование данных в веб-интерфейсе
Мне нужно кэшировать коллекцию объектов, которая в основном статична (может иметь изменения 1 раз в день), которая доступна в моей службе ASP.NET Web API OData. Этот набор результатов используется во всех вызовах (что означает не специфический клиентский вызов), поэтому его необходимо кэшировать на уровне приложения.
Я сделал кучу поиска в кешировании в Web API, но все результаты были посвящены "кэшированию вывода". Это не то, что я ищу здесь. Я хочу кэшировать коллекцию "Люди" для повторного использования при последующих вызовах (может иметь скользящее окончание).
Мой вопрос в том, что, поскольку это все еще просто ASP.NET, я использую традиционные методы кэширования приложений для сохранения этой коллекции в памяти или что-то еще мне нужно сделать? Эта коллекция напрямую не возвращается пользователю, а скорее используется в качестве источника за кулисами для запросов OData через вызовы API. Для меня нет оснований выходить в базу данных при каждом вызове, чтобы получить точную информацию о каждом вызове. По истечении срока оно должно быть достаточно.
Кто-нибудь знает, как правильно кэшировать данные в этом сценарии?
Ответы
Ответ 1
Да, кэширование вывода - это не то, что вы ищете. Вы можете кэшировать данные в памяти с помощью MemoryCache, например http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx. Однако вы потеряете эти данные, если пул приложений будет переработан. Другой вариант - использовать распределенный кеш, такой как AppFabric Cache или MemCache, чтобы назвать несколько.
Ответ 2
Решение я закончило использование MemoryCache
в пространстве имен System.Runtime.Caching
. Вот код, который закончился для кэширования моей коллекции:
//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;
Вот еще один способ, который я нашел, используя Lazy<T>
, чтобы учесть блокировку и concurrency. Общий кредит идет на этот пост: Как бороться с дорогостоящими операциями здания с использованием 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
}