I'm hoping this is the correct place to ask this, but after recently experiencing some strange behaviour I realised after doing some research that when using .NET memory cache and you retrieve an object from cache you retrieve a reference to that object in cache, rather than a copy of the object, so any updates to the object will persist in cache.
In the example below the student is updated in the StudentController
, and retrieved again the CourseController
, with the student containing the updated value without having to refresh the cache.
My initial approach was to clear the cached students collection after updating the DB (because I thought the cached version wouldn't have included the update), but given that this persistence exists is there a need to repopulate the cache again once the database has been updated?
// Student controller
public class StudentController : Controller
{
// omitted for brevity.
public ActionResult UpdateStudent(int id)
{
var student = CollegeCache.Students[id];
student.FirstName = "SpongeBob"
studentRepository.update(student)
// CollegeCache.clearStudents();
}
}
// Course controller
public class CourseController : Controller
{
// omitted for brevity.
public ActionResult GetCoursesDetails(int id)
{
var student = CollegeCache.Students[id];
// here student.FirstName will be "SpongeBob", and not it's original value.
}
}
// Cache helper class
public static class CollegeCache
{
private static readonly ObjectCache cache = new MemoryCache("College");
private static object locker = new object();
public static readonly string StudentsKey = "StudentsKey";
// Clears the entire cache store.
public static void Clear()
{
foreach (var item in cache)
cache.Remove(item.Key);
}
// Clears a single cache entry.
public static void Clear(string key)
{
cache.Remove(key);
}
// Add to cache helper
private static void Add(string key, object value, DateTimeOffset expiration,
CacheItemPriority priority = CacheItemPriority.Default)
{
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = expiration;
policy.Priority = priority;
var item = new CacheItem(key, value);
cache.Add(item, policy);
}
// Students cache store.
public static Dictionary<int, Student> Students
{
get
{
var dictionary = cache[StudentsKey] as Dictionary<int, Student>;
if (dictionary == null)
{
lock (locker)
{
dictionary = db.Students.All().ToList().ToDictionary(a => a.Id);
Add(StudentsKey, dictionary, DateTime.Now.AddHours(1));
}
}
return dictionary;
}
}
// Clears the users cache store.
public static void ClearStudents()
{
Clear(StudentsKey);
}
}