如何处理缓存中的更新对象?

时间:2015-09-15 21:41:11

标签: c# asp.net-mvc caching

我希望这是一个正确的问题,但是在我最近遇到一些奇怪的行为之后,我意识到在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);
        }
    }   

1 个答案:

答案 0 :(得分:1)

一般来说,如果更新基础数据源中的数据,则还必须在缓存中更新数据,否则将来缓存中的数据获取状态将比数据库中的数据更陈旧且不稳定。你会失去同步。你可以清除缓存并重新填充,但每次有更新时这都是一件昂贵的事情 - 由于上述原因,不建议这样做。只有在数据库中成功更新数据然后更新缓存时才应更新。

由于您更新了相关对象,因此应自动更新缓存&#34;自动&#34;在某种程度上(假设您从缓存中获取了对象)但是我仍然会在缓存端进行显式更新,因为如果数据源引发错误(即SQLException)会怎样?您需要确保有问题的对象准确更新,否则您会遇到数据完整性问题:)