Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching Data in Web API

I have the need to cache a collection of objects that is mostly static (might have changes 1x per day) that is avaliable in my ASP.NET Web API OData service. This result set is used across calls (meaning not client call specific) so it needs to be cached at the application level.

I did a bunch of searching on 'caching in Web API' but all of the results were about 'output caching'. That is not what I'm looking for here. I want to cache a 'People' collection to be reused on subsequent calls (might have a sliding expiration).

My question is, since this is still just ASP.NET, do I use traditional Application caching techniques for persisting this collection in memory, or is there something else I need to do? This collection is not directly returned to the user, but rather used as the source behind the scenes for OData queries via API calls. There is no reason for me to go out to the database on every call to get the exact same information on every call. Expiring it hourly should suffice.

Any one know how to properly cache the data in this scenario?

like image 204
atconway Avatar asked May 08 '13 14:05

atconway


People also ask

What is caching in API?

The Cache API is a system for storing and retrieving network requests and their corresponding responses. These might be regular requests and responses created in the course of running your application, or they could be created solely for the purpose of storing data for later use.

Is caching possible in Web API?

Caching is very common to make applications performant and scalable. If a result is already computed by the application, it is cached in a store so that next time when the same request comes, cached result can be fetched instead of processing the request again.

What types of caching exists for web APIs?

Edge caching or CDN. Database caching. Server caching (API caching) Browser caching.


1 Answers

The solution I ended up using involved MemoryCache in the System.Runtime.Caching namespace. Here is the code that ended up working for caching my collection:

//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; 

Here is another way I found using Lazy<T> to take into account locking and concurrency. Total credit goes to this post: 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 } 
like image 77
atconway Avatar answered Sep 19 '22 13:09

atconway