What is the recommended way to remove a large number of items from a MemoryCache instance?
Based on the discussion around this question it seems that the preferred approach is to use a single cache for the whole application and use namespaces for keys to allow multiple logical types of items to be cached in the same instance.
However, using a single cache instance leaves the problem of expiring (removing) a large number of items from the cache. Particularly in the case where all items of a certain logical type must be expired.
At the moment the only solution I found was based on the answer to this question but it's really not very good from a performance stand-point since you would have to enumerate through all keys in the cache, and test the namespace, which could be quite time-consuming!
The only work-around I came up with at the moment is to create a thin wrapper for all the objects in the cache with a version number and whenever an object is accessed, discard it if the cached version doesn't match the current version. So whenever I need to clear all items of a certain type, I would bump up the current version number rendering all cached items invalid.
The work-around above seems pretty solid. But I can't help but wonder if there isn't a more straight-forward way to accomplish the same?
This is my current implementation:
private class MemCacheWrapper<TItemType>
where TItemType : class
{
private int _version;
private Guid _guid;
private System.Runtime.Caching.ObjectCache _cache;
private class ThinWrapper
{
public ThinWrapper(TItemType item, int version)
{
Item = item;
Version = version;
}
public TItemType Item { get; set; }
public int Version { get; set; }
}
public MemCacheWrapper()
{
_cache = System.Runtime.Caching.MemoryCache.Default;
_version = 0;
_guid = Guid.NewGuid();
}
public TItemType Get(int index)
{
string key = string.Format("{0}_{1}", _guid, index);
var lvi = _cache.Get(key) as ThinWrapper;
if (lvi == null || lvi.Version != _version)
{
return null;
}
return lvi.Item;
}
public void Put(int index, TItemType item)
{
string key = string.Format("{0}_{1}", _guid, index);
var cip = new System.Runtime.Caching.CacheItemPolicy();
cip.SlidingExpiration.Add(TimeSpan.FromSeconds(30));
_cache.Set(key, new ThinWrapper(item, _version), cip);
}
public void Clear()
{
_version++;
}
}