【发布时间】:2015-09-15 21:41:10
【问题描述】:
我希望这是问这个问题的正确地方,但是在最近经历了一些奇怪的行为之后,我在执行some research 之后意识到,当使用 .NET 内存缓存并从缓存中检索对象时,您会检索到该对象的引用缓存中的对象,而不是对象的副本,因此对对象的任何更新都将保留在缓存中。
在下面的示例中,学生在StudentController 中更新,并再次检索CourseController,学生包含更新后的值而无需刷新缓存。
我最初的方法是在更新数据库后清除缓存的学生集合(因为我认为缓存的版本不会包含更新),但鉴于存在这种持久性,是否需要再次重新填充缓存数据库已更新?
// 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);
}
}
【问题讨论】:
-
好吧。如果您更新底层数据源中的数据,那么您还必须在缓存中更新它,否则缓存中的数据未来获取的状态将比数据库中的数据陈旧且不稳定。你会不同步。您可以清除缓存并重新填充,但每次有更新时这都是一件昂贵的事情。您应该只在更新数据库中的数据然后更新缓存时更新
-
我注意到的一件事是您没有显示“缓存”的定义位置和方式。如果您可以发布它会很好,但无论如何,我上面的评论仍然适用:)
-
@Ahmedilyas 我知道缓存存储需要与数据存储同步,这就是我试图解释的。当我更新存储在缓存中的对象时,我不需要清除和刷新缓存 - 更新对象时会更新缓存(即,无需刷新缓存)。我现在更新了代码以包含完整的缓存实现。
-
感谢代码更新马克。是的-因为您更新了有问题的对象,所以缓存应该以某种方式“自动”更新(前提是您从缓存中获取了对象)但是我仍然会在缓存端进行显式更新,因为如果数据源怎么办抛出错误(即 SQLException)?您需要确保有问题的对象被准确更新:) 好东西!
-
@Ahmedilyas 谢谢,这种方法很有意义。
标签: c# asp.net-mvc caching