using Newtonsoft.Json; | |
using StackExchange.Redis; | |
using System; | |
using System.Collections.Generic; | |
using System.Configuration; | |
using System.Linq; | |
using System.Web; | |
namespace CacheAsideDemo.Data | |
{ | |
public class Cache | |
{ | |
private static ConnectionMultiplexer __connection; | |
private static ConnectionMultiplexer Connection | |
{ | |
get | |
{ | |
return __connection ?? | |
( __connection = ConnectionMultiplexer.Connect( ConfigurationManager.AppSettings["RedisConnString"] ) ); | |
} | |
} | |
public T GetFromCache<T>( string key, Func<T> missCallback ) | |
{ | |
T value; | |
var redis = Connection.GetDatabase(); | |
var serializedValue = redis.StringGet( key ); | |
if ( !serializedValue.IsNullOrEmpty ) // Hit! | |
{ | |
value = JsonConvert.DeserializeObject<T>( serializedValue ); | |
} | |
else // Miss - load from callback and store in cache with expiry time of 5 minutes | |
{ | |
value = missCallback(); | |
redis.StringSet( key, JsonConvert.SerializeObject( value ), TimeSpan.FromMinutes( 5 ) ); | |
} | |
return value; | |
} | |
public void InvalidateCacheEntry( string key ) | |
{ | |
var redis = Connection.GetDatabase(); | |
redis.KeyDelete( key ); | |
} | |
} | |
} |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Web; | |
using CacheAsideDemo.Models; | |
using StackExchange.Redis; | |
namespace CacheAsideDemo.Data | |
{ | |
public class CacheAsideProductService : IProductService | |
{ | |
private IProductService _underlyingService; | |
private Cache _cache; | |
public CacheAsideProductService( IProductService underlyingService, Cache cache ) | |
{ | |
_underlyingService = underlyingService; | |
_cache = cache; | |
} | |
public Product Get( Guid id ) | |
{ | |
var cacheKey = String.Format( "Product_{0}", id ); | |
return _cache.GetFromCache<Product>( cacheKey, () => _underlyingService.Get( id ) ); | |
} | |
public void Update( Guid id, Product product ) | |
{ | |
var cacheKey = String.Format( "Product_{0}", id ); | |
_underlyingService.Update( id, product ); | |
_cache.InvalidateCacheEntry( cacheKey ); | |
} | |
} | |
} |
using CacheAsideDemo.Data; | |
using CacheAsideDemo.Models; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Http; | |
using System.Web.Http; | |
namespace CacheAsideDemo.Controllers | |
{ | |
[RoutePrefix( "api/products" )] | |
public class ProductController : ApiController | |
{ | |
//IProductService _service = new ProductService(); // No Caching | |
IProductService _service = new CacheAsideProductService( new ProductService(), new Cache() ); | |
[HttpGet, Route( "{id:guid}" )] | |
public Product Get( Guid id ) | |
{ | |
return _service.Get( id ); | |
} | |
[HttpPut, Route( "{id:guid}" )] | |
public Product Update( Guid id, Product product ) | |
{ | |
_service.Update( id, product ); | |
return product; | |
} | |
} | |
} |
using CacheAsideDemo.Data; | |
using CacheAsideDemo.Models; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Http; | |
using System.Web.Http; | |
namespace CacheAsideDemo.Controllers | |
{ | |
[RoutePrefix( "api/products" )] | |
public class ProductController : ApiController | |
{ | |
IProductService _service = new ProductService(); | |
[HttpGet, Route( "{id:guid}" )] | |
public Product Get( Guid id ) | |
{ | |
return _service.Get( id ); | |
} | |
[HttpPut, Route( "{id:guid}" )] | |
public Product Update( Guid id, Product product ) | |
{ | |
_service.Update( id, product ); | |
return product; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment