我需要在ASP.NET Web API OData服务中缓存大部分是静态的(可能每天更改1次)的对象集合。此结果集用于跨调用(意味着不是特定于客户端调用),因此需要在应用程序级别缓存。
我做了一些关于'在Web API中缓存'的搜索,但所有结果都是关于'输出缓存'。这不是我在这里寻找的。我想缓存一个'People'集合,以便在后续调用中重用(可能有一个滑动过期)。
我的问题是,既然这仍然只是ASP.NET,我是否使用传统的应用程序缓存技术将此集合持久存储在内存中,或者我还需要做些什么呢?此集合不直接返回给用户,而是通过API调用用作OData查询的幕后源。我没有理由在每次通话时都去数据库,以便在每次通话时获得完全相同的信息。每小时到期就足够了。
任何人都知道如何在这种情况下正确缓存数据?
答案 0 :(得分:40)
我最终在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>
来考虑锁定和并发的另一种方法。总信用额转到此帖子: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 :(得分:26)
是的,输出缓存不是您想要的。您可以使用MemoryCache将数据缓存到内存中,例如http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx。但是,如果应用程序池被回收,您将丢失该数据。另一种选择是使用AppFabric Cache或MemCache等分布式缓存来命名。