2013-05-08 8 views
29

ASP.NET Web API ODataサービスでは、ほとんど静的(1日に1回の変更がある可能性があります)のオブジェクトのコレクションをキャッシュする必要があります。この結果セットは、コール全体(つまり、クライアントコール固有ではない)で使用されるため、アプリケーションレベルでキャッシュする必要があります。Web APIでデータをキャッシュする

私は 'Web APIのキャッシュ'を検索しましたが、すべての結果は「出力キャッシュ」に関するものでした。それは私がここで探しているものではありません。私は後続の呼び出しで再利用される 'People'コレクションをキャッシュしたい(スライディングの有効期限があるかもしれない)。

これは単なるASP.NETなので、私はこのコレクションをメモリ内に永続化するための従来のアプリケーションキャッシュテクニックを使用しますか、それとも何か他に必要なことはありますか?このコレクションはではなく、が直接ユーザーに返されますが、APIコールを使用してODataクエリの背後にあるソースとして使用されます。 正確なをすべての呼び出しで同じ情報にするために、すべての呼び出しでデータベースにアクセスする必要はありません。それを時間切れにするだけで十分です。

このシナリオでデータを正しくキャッシュする方法を知っている人はいますか?

答えて

21

はい、出力キャッシュはあなたが探しているものではありません。 MemoryCacheを使用してデータをメモリにキャッシュすることができます(例:http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx)。ただし、アプリケーションプールがリサイクルされると、そのデータは失われます。もう一つのオプションは、AppFabric CacheやMemCacheのような分散キャッシュを使用していくつかの名前を付けることです。

+0

はい、これを書いた後、私は完璧に見える 'System.Runtime.Caching'名前空間に' MemoryCache'を発見しました。 AppPoolがリサイクルするとデータを失う可能性があるという警告は、*すべての* API呼び出しでDBを再呼び出しするのを防ぐためです。 'MemoryCache.Get()'と 'MemoryCache.Add()'を使うと、私にとってはうまくいくようです。 'AddOrGetExisting()'はクールだが、私の状況ではうまくいかなかった。呼び出しの前にDBからデータを取得する必要があります。私は30分の「AbsoluteExpiration」を設定しました。 – atconway

+5

途中で人々を助けるためのマーカーとして、Azureの推奨されるキャッシング技術は現在Redisです。 APIのインスタンスが2つ以上ある場合は、Redisまたは別の分散キャッシュが必要です。 Azure Managed Cacheは非常に隠されており、Powershellからしかアクセスできません。彼らは以前にそれを使用した人々を助けるためにそこにそれを保持しているだけです。 –

+0

Redisは、あなたがやっているすべての作業がWebApiデータコールをキャッシュしている場合には高価です。 –

31

解決方法は、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>を使用した別の方法があります。総与信はこの記事に行く:How to deal with costly building operations using 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 
} 
+1

このGetFromCacheメソッドを呼び出すにはどうすればよいですか?valueFactoryパラメータでpaasに必要なものは?リポジトリを呼び出すGetの出力を保存する必要がある場合は、それを使用して後続の呼び出しで使用しますか? – F11

関連する問題