-
Notifications
You must be signed in to change notification settings - Fork 165
API documentation (v 2.x)
See QuickStart docs
The best way to use LazyCache is through the GetOrAdd method. It uses generics to save you any type casting hassle and a Func to ensure you only call you cacheable delegate once.
// Create the cache
IAppCache cache = new CachingService();
// Get all products from the cache, or get from db and cache results
var products = cache.GetOrAdd("productService-getProducts", () => dbContext.Products.ToList());
Each cache entry must have a unique key, where the key is unique to the underlying cache instance, which by default is the shared MemoryCache.Default.
Constructing a unique key is left to the developer, but a good best practice is to cache the results of a chosen methods call and adopt convention of className-methodName-argument1Value-argument2Value
etc for the method you are adding caching to. Following this naming convention makes it easy to examine keys at run-time and establish the source and guarantees uniqueness.
For example
public class ProductService() {
...
public Product GetProductById(int id){
var key = string.Format("ProductService-GetProductById-{0}", id); //or use string interpolation
return cache.GetOrAdd(key, () => dbContext.Products.Get(id));
}
...
}
var products = cache.GetOrAdd("all-products", () => dbContext.Products.ToList(), DateTimeOffset.Now.AddMinutes(5));
var products = cache.GetOrAdd("all-products", () => dbContext.Products.ToList(), TimeSpan.FromMinutes(5));
If the thing you are caching is fetched asynchronously, i.e. it returns a Task<Something>
you should use GetOrAddAsync()
.
If the thing you are caching is fetched synchronously, i.e. it does not return as task, you should use GetOrAdd()
.
Use GetOrAddAsync to cache tasks. In this example we demonstrate using lazy cache to cache an async Entity Framework query inside a webapi controller:
[HttpGet]
[Route("api/products")]
public async Task<Product> Get(int id)
{
Func<Task<Product>> cacheableAsyncFunc = () => dbContext.Products.GetAsync(id);
var cachedProducts = await cache.GetOrAddAsync($"ProductsController-Get-{id}", cacheableAsyncFunc);
return cachedProducts;
// Or just do it all in one line if you prefer
// return await cache.GetOrAddAsync($"ProductsController-Get-{id}", () => dbContext.Products.GetAsync(id));
}
Most of the time all you need is GetOrAdd but sometimes you might need to force an item into the cache
// Get the cache (or use a DI container)
IAppCache cache = new CachingService();
// Get all products from db
var products = dbContext.Products.ToList();
// Add them to the cache so we can retrieve them up to 20 mins later
cache.Add("all-products", products);
// Add products to the cache for at most one minute
cache.Add("all-products", products, DateTimeOffset.Now.AddMinutes(1));
// Add products to the cache and keep them there as long as they
// have been accessed in the last 5 minutes
cache.Add("all-products", products, new TimeSpan(0, 5, 0));
cache.GetOrAdd("some-key", entry => {
var thingWithAnExpiryDate = GetTheThingToCache();
DateTimeOffset expiryDate = thingWithAnExpiryDate.Expires;
// can set expiry date using a DateTimeOffset or a TimeSpan from now.
entry.SetAbsoluteExpiration(expiryDate);
return thingWithAnExpiryDate;
});
Get notified when something is removed, set cache entry priorities and more by using a MemoryCacheEntryOptions
// Add products to the cache with an unremovable custom cache priority
// add a custom eviction callback
var options = new MemoryCacheEntryOptions(){
Priority = CacheItemPriority.NeverRemove
};
options.RegisterPostEvictionCallback((key, value, reason, state) =>
{
log.Write("Products removed from cache")
});
cache.Add("all-products", products, options);
If you need the last version of your cached data, you can access it by as the second parameter of the callback delegate:
var options = new MemoryCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddMilliseconds(100) // about to expire!
}.RegisterPostEvictionCallback(
(key, value, reason, state) => Debug.Write("this value has just been removed: " + value.ToString())
);
cache.Add("all-products", products, options);
If you have already cached something you can retrieve it, without the need for any type checking or casting, using Get
. If its not cached null will be returned.
// Get the cache
IAppCache cache = new CachingService();
// Get product from the cache based on a key
var product = cache.Get<Product>("product-with-id-1");
If it is cached it will be removed, if not no error will be thrown
// Remove the products from the cache
cache.Remove("all-products");
// Change the default cache duration from 20 minutes to 3 minutes
var cache = new CachingService() { DefaultCachePolicy.DefaultCacheDurationSeconds = 60 * 3 };