How to cache data in a MVC application

后端 未结 14 1146
鱼传尺愫
鱼传尺愫 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:15

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

        public string[] GetNames()
        {
          string[] names = Cache["names"] as string[];
          if(names == null) //not in cache
          {
            names = DB.GetNames();
            Cache["names"] = names;
          }
          return names;
        }
    

    A bit simplified but I guess that would work. This is not MVC specific and I have always used this method for caching data.

    0 讨论(0)
  • Here's an improvement to Hrvoje Hudo's answer. This implementation has a couple of key improvements:

    • Cache keys are created automatically based on the function to update data and the object passed in that specifies dependencies
    • Pass in time span for any cache duration
    • Uses a lock for thread safety

    Note that this has a dependency on Newtonsoft.Json to serialize the dependsOn object, but that can be easily swapped out for any other serialization method.

    ICache.cs

    public interface ICache
    {
        T GetOrSet<T>(Func<T> getItemCallback, object dependsOn, TimeSpan duration) where T : class;
    }
    

    InMemoryCache.cs

    using System;
    using System.Reflection;
    using System.Runtime.Caching;
    using Newtonsoft.Json;
    
    public class InMemoryCache : ICache
    {
        private static readonly object CacheLockObject = new object();
    
        public T GetOrSet<T>(Func<T> getItemCallback, object dependsOn, TimeSpan duration) where T : class
        {
            string cacheKey = GetCacheKey(getItemCallback, dependsOn);
            T item = MemoryCache.Default.Get(cacheKey) as T;
            if (item == null)
            {
                lock (CacheLockObject)
                {
                    item = getItemCallback();
                    MemoryCache.Default.Add(cacheKey, item, DateTime.Now.Add(duration));
                }
            }
            return item;
        }
    
        private string GetCacheKey<T>(Func<T> itemCallback, object dependsOn) where T: class
        {
            var serializedDependants = JsonConvert.SerializeObject(dependsOn);
            var methodType = itemCallback.GetType();
            return methodType.FullName + serializedDependants;
        }
    }
    

    Usage:

    var order = _cache.GetOrSet(
        () => _session.Set<Order>().SingleOrDefault(o => o.Id == orderId)
        , new { id = orderId }
        , new TimeSpan(0, 10, 0)
    );
    
    0 讨论(0)
  • 2020-11-22 12:17

    For .NET 4.5+ framework

    add reference: System.Runtime.Caching

    add using statement: using System.Runtime.Caching;

    public string[] GetNames()
    { 
        var noms = System.Runtime.Caching.MemoryCache.Default["names"];
        if(noms == null) 
        {    
            noms = DB.GetNames();
            System.Runtime.Caching.MemoryCache.Default["names"] = noms; 
        }
    
        return ((string[])noms);
    }
    

    In the .NET Framework 3.5 and earlier versions, ASP.NET provided an in-memory cache implementation in the System.Web.Caching namespace. In previous versions of the .NET Framework, caching was available only in the System.Web namespace and therefore required a dependency on ASP.NET classes. In the .NET Framework 4, the System.Runtime.Caching namespace contains APIs that are designed for both Web and non-Web applications.

    More info:

    • https://msdn.microsoft.com/en-us/library/dd997357(v=vs.110).aspx

    • https://docs.microsoft.com/en-us/dotnet/framework/performance/caching-in-net-framework-applications

    0 讨论(0)
  • 2020-11-22 12:17
    HttpContext.Current.Cache.Insert("subjectlist", subjectlist);
    
    0 讨论(0)
  • 2020-11-22 12:25
    public sealed class CacheManager
    {
        private static volatile CacheManager instance;
        private static object syncRoot = new Object();
        private ObjectCache cache = null;
        private CacheItemPolicy defaultCacheItemPolicy = null;
    
        private CacheEntryRemovedCallback callback = null;
        private bool allowCache = true;
    
        private CacheManager()
        {
            cache = MemoryCache.Default;
            callback = new CacheEntryRemovedCallback(this.CachedItemRemovedCallback);
    
            defaultCacheItemPolicy = new CacheItemPolicy();
            defaultCacheItemPolicy.AbsoluteExpiration = DateTime.Now.AddHours(1.0);
            defaultCacheItemPolicy.RemovedCallback = callback;
            allowCache = StringUtils.Str2Bool(ConfigurationManager.AppSettings["AllowCache"]); ;
        }
        public static CacheManager Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                        {
                            instance = new CacheManager();
                        }
                    }
                }
    
                return instance;
            }
        }
    
        public IEnumerable GetCache(String Key)
        {
            if (Key == null || !allowCache)
            {
                return null;
            }
    
            try
            {
                String Key_ = Key;
                if (cache.Contains(Key_))
                {
                    return (IEnumerable)cache.Get(Key_);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception)
            {
                return null;
            }
        }
    
        public void ClearCache(string key)
        {
            AddCache(key, null);
        }
    
        public bool AddCache(String Key, IEnumerable data, CacheItemPolicy cacheItemPolicy = null)
        {
            if (!allowCache) return true;
            try
            {
                if (Key == null)
                {
                    return false;
                }
    
                if (cacheItemPolicy == null)
                {
                    cacheItemPolicy = defaultCacheItemPolicy;
                }
    
                String Key_ = Key;
    
                lock (Key_)
                {
                    return cache.Add(Key_, data, cacheItemPolicy);
                }
            }
            catch (Exception)
            {
                return false;
            }
        }
    
        private void CachedItemRemovedCallback(CacheEntryRemovedArguments arguments)
        {
            String strLog = String.Concat("Reason: ", arguments.RemovedReason.ToString(), " | Key-Name: ", arguments.CacheItem.Key, " | Value-Object: ", arguments.CacheItem.Value.ToString());
            LogManager.Instance.Info(strLog);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 12:29

    Here's a nice and simple cache helper class/service I use:

    using System.Runtime.Caching;  
    
    public class InMemoryCache: ICacheService
    {
        public T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class
        {
            T item = MemoryCache.Default.Get(cacheKey) as T;
            if (item == null)
            {
                item = getItemCallback();
                MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(10));
            }
            return item;
        }
    }
    
    interface ICacheService
    {
        T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class;
    }
    

    Usage:

    cacheProvider.GetOrSet("cache key", (delegate method if cache is empty));
    

    Cache provider will check if there's anything by the name of "cache id" in the cache, and if there's not, it will call a delegate method to fetch data and store it in cache.

    Example:

    var products=cacheService.GetOrSet("catalog.products", ()=>productRepository.GetAll())
    
    0 讨论(0)
提交回复
热议问题