ASP.NET Web API ODataサービスで利用可能な、ほとんど静的な(1日に1倍の変更がある可能性がある)オブジェクトのコレクションをキャッシュする必要があります。この結果セットはコール全体で使用されるため(クライアントコール固有ではありません)、アプリケーションレベルでキャッシュする必要があります。
私は「Web APIでのキャッシュ」を検索しましたが、結果はすべて「出力キャッシュ」に関するものでした。それは私がここで探しているものではありません。 「People」コレクションをキャッシュして、後続の呼び出しで再利用します(スライド式の有効期限があります)。
私の質問は、これはまだ単なるASP.NETであるため、このコレクションをメモリに永続化するために従来のアプリケーションキャッシング手法を使用するのか、それとも他に何かする必要があるのですか?このコレクションはnotユーザーに直接返されますが、API呼び出しを介したODataクエリの背後でソースとして使用されます。すべての呼び出しでexact同じ情報を取得するために、すべての呼び出しでデータベースにアクセスする理由はありません。 1時間ごとに期限切れで十分です。
このシナリオでデータを適切にキャッシュする方法を知っている人はいますか?
はい、出力キャッシュはあなたが探しているものではありません。 http://msdn.Microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx のように、MemoryCacheを使用してメモリにデータをキャッシュできます。ただし、アプリケーションプールがリサイクルされると、そのデータは失われます。別のオプションは、AppFabric CacheやMemCacheなどの分散キャッシュを使用して、いくつかの名前を付けることです。
使用したソリューションは、System.Runtime.Caching
名前空間のMemoryCache
に関係していました。コレクションをキャッシュするために機能するようになったコードは次のとおりです。
//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>
を使用して見つけた別の方法を次に示します。合計クレジットは、この投稿に行きます: 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
}