41

我需要缓存在我的 ASP.NET Web API OData 服务中可用的主要是静态的对象集合(可能每天更改 1 次)。此结果集用于跨调用(意味着不是特定于客户端调用),因此需要在应用程序级别进行缓存。

我对“Web API 中的缓存”进行了大量搜索,但所有结果都是关于“输出缓存”的。这不是我在这里寻找的。我想缓存一个“人”集合,以便在后续调用中重用(可能有一个滑动到期)。

我的问题是,由于这仍然只是 ASP.NET,我是否使用传统的应用程序缓存技术将这个集合保存在内存中,还是我需要做其他事情?此集合直接返回给用户,而是用作通过 API 调用进行 OData 查询的幕后来源。我没有理由在每次通话时都访问数据库以在每次通话中获取完全相同的信息。每小时到期就足够了。

有人知道如何在这种情况下正确缓存数据吗?

4

2 回答 2

51

我最终使用的解决方案涉及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>考虑锁定和并发性的方法。总功劳归于这篇文章:如何使用 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
}
于 2013-05-08T17:41:03.983 回答
27

是的,输出缓存不是您想要的。您可以使用 MemoryCache 将数据缓存在内存中,例如http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.aspx。但是,如果应用程序池被回收,您将丢失该数据。另一种选择是使用分布式缓存,例如 AppFabric Cache 或 MemCache 等等。

于 2013-05-08T17:04:54.670 回答