How to cache data in a MVC application

后端 未结 14 1145
鱼传尺愫
鱼传尺愫 2020-11-22 11:39

I have read lots of information about page caching and partial page caching in a MVC application. However, I would like to know how you would cache data.

In my scena

相关标签:
14条回答
  • 2020-11-22 12:05

    I will say implementing Singleton on this persisting data issue can be a solution for this matter in case you find previous solutions much complicated

     public class GPDataDictionary
    {
        private Dictionary<string, object> configDictionary = new Dictionary<string, object>();
    
        /// <summary>
        /// Configuration values dictionary
        /// </summary>
        public Dictionary<string, object> ConfigDictionary
        {
            get { return configDictionary; }
        }
    
        private static GPDataDictionary instance;
        public static GPDataDictionary Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new GPDataDictionary();
                }
                return instance;
            }
        }
    
        // private constructor
        private GPDataDictionary() { }
    
    }  // singleton
    
    0 讨论(0)
  • 2020-11-22 12:06

    Steve Smith did two great blog posts which demonstrate how to use his CachedRepository pattern in ASP.NET MVC. It uses the repository pattern effectively and allows you to get caching without having to change your existing code.

    http://ardalis.com/Introducing-the-CachedRepository-Pattern

    http://ardalis.com/building-a-cachedrepository-via-strategy-pattern

    In these two posts he shows you how to set up this pattern and also explains why it is useful. By using this pattern you get caching without your existing code seeing any of the caching logic. Essentially you use the cached repository as if it were any other repository.

    0 讨论(0)
  • I'm referring to TT's post and suggest the following approach:

    Reference the System.Web dll in your model and use System.Web.Caching.Cache

    public string[] GetNames()
    { 
        var noms = Cache["names"];
        if(noms == null) 
        {    
            noms = DB.GetNames();
            Cache["names"] = noms; 
        }
    
        return ((string[])noms);
    }
    

    You should not return a value re-read from the cache, since you'll never know if at that specific moment it is still in the cache. Even if you inserted it in the statement before, it might already be gone or has never been added to the cache - you just don't know.

    So you add the data read from the database and return it directly, not re-reading from the cache.

    0 讨论(0)
  • 2020-11-22 12:09

    Extending @Hrvoje Hudo's answer...

    Code:

    using System;
    using System.Runtime.Caching;
    
    public class InMemoryCache : ICacheService
    {
        public TValue Get<TValue>(string cacheKey, int durationInMinutes, Func<TValue> getItemCallback) where TValue : class
        {
            TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
            if (item == null)
            {
                item = getItemCallback();
                MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
            }
            return item;
        }
    
        public TValue Get<TValue, TId>(string cacheKeyFormat, TId id, int durationInMinutes, Func<TId, TValue> getItemCallback) where TValue : class
        {
            string cacheKey = string.Format(cacheKeyFormat, id);
            TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
            if (item == null)
            {
                item = getItemCallback(id);
                MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
            }
            return item;
        }
    }
    
    interface ICacheService
    {
        TValue Get<TValue>(string cacheKey, Func<TValue> getItemCallback) where TValue : class;
        TValue Get<TValue, TId>(string cacheKeyFormat, TId id, Func<TId, TValue> getItemCallback) where TValue : class;
    }
    

    Examples

    Single item caching (when each item is cached based on its ID because caching the entire catalog for the item type would be too intensive).

    Product product = cache.Get("product_{0}", productId, 10, productData.getProductById);
    

    Caching all of something

    IEnumerable<Categories> categories = cache.Get("categories", 20, categoryData.getCategories);
    

    Why TId

    The second helper is especially nice because most data keys are not composite. Additional methods could be added if you use composite keys often. In this way you avoid doing all sorts of string concatenation or string.Formats to get the key to pass to the cache helper. It also makes passing the data access method easier because you don't have to pass the ID into the wrapper method... the whole thing becomes very terse and consistant for the majority of use cases.

    0 讨论(0)
  • 2020-11-22 12:09

    I have used it in this way and it works for me. https://msdn.microsoft.com/en-us/library/system.web.caching.cache.add(v=vs.110).aspx parameters info for system.web.caching.cache.add.

    public string GetInfo()
    {
         string name = string.Empty;
         if(System.Web.HttpContext.Current.Cache["KeyName"] == null)
         {
             name = GetNameMethod();
             System.Web.HttpContext.Current.Cache.Add("KeyName", name, null, DateTime.Noew.AddMinutes(5), Cache.NoSlidingExpiration, CacheitemPriority.AboveNormal, null);
         }
         else
         {
             name = System.Web.HttpContext.Current.Cache["KeyName"] as string;
         }
    
          return name;
    
    }
    
    0 讨论(0)
  • 2020-11-22 12:11

    I use two classes. First one the cache core object:

    public class Cacher<TValue>
        where TValue : class
    {
        #region Properties
        private Func<TValue> _init;
        public string Key { get; private set; }
        public TValue Value
        {
            get
            {
                var item = HttpRuntime.Cache.Get(Key) as TValue;
                if (item == null)
                {
                    item = _init();
                    HttpContext.Current.Cache.Insert(Key, item);
                }
                return item;
            }
        }
        #endregion
    
        #region Constructor
        public Cacher(string key, Func<TValue> init)
        {
            Key = key;
            _init = init;
        }
        #endregion
    
        #region Methods
        public void Refresh()
        {
            HttpRuntime.Cache.Remove(Key);
        }
        #endregion
    }
    

    Second one is list of cache objects:

    public static class Caches
    {
        static Caches()
        {
            Languages = new Cacher<IEnumerable<Language>>("Languages", () =>
                                                              {
                                                                  using (var context = new WordsContext())
                                                                  {
                                                                      return context.Languages.ToList();
                                                                  }
                                                              });
        }
        public static Cacher<IEnumerable<Language>> Languages { get; private set; }
    }
    
    0 讨论(0)
提交回复
热议问题