Caching
A key/value layer in front of your read operations that skips the round trip entirely once something is already in memory.
What it is
Pass a cacheKey to a read operation and the result is stored for reuse on the next call with the same key, backed by an in-memory dictionary by default with a 180-minute expiration.
Using it
var cache = new MemoryCache();
var products = connection.QueryAll<Product>(cacheKey: "products", cache: cache);
Keys should be unique to the query they represent — a common convention is ClassName-Property-Value, e.g. Product-Id-5, so collisions and stale reads don’t creep in as more call sites start caching.
Expiration
Pass cacheItemExpiration (in minutes) alongside cacheKey to override the default, or call cache.Remove(key) to invalidate an entry as soon as the underlying data changes.
Bringing your own cache
Implementing ICache swaps the in-memory store for anything else — Redis, a distributed cache, a JSON file on disk.
public class JsonCache : ICache
{
public void Add<T>(string key, T value, int expiration = 180, bool throwException = true) { ... }
public void Add<T>(CacheItem<T> item, bool throwException = true) { ... }
public bool Contains(string key) { ... }
public CacheItem<T> Get<T>(string key, bool throwException = true) { ... }
public void Remove(string key, bool throwException = true) { ... }
public void Clear() { ... }
}
Each of these methods also has an
Asynccounterpart on the interface.
Pass the instance into BaseRepository or DbRepository’s constructor and every call through that repository uses it automatically.
using (var repository = new DbRepository<SqlConnection>(connectionString, new JsonCache()))
{
var products = repository.QueryAll<Product>(cacheKey: "products");
}