1. 程式人生 > >Asp.net Core2.0 快取 MemoryCache 和 Redis

Asp.net Core2.0 快取 MemoryCache 和 Redis

 

 

自從使用Asp.net Core2.0 以來,不停摸索,查閱資料,這方面的資料是真的少,因此,在前人的基礎上,摸索出了Asp.net Core2.0 快取 MemoryCache 和 Redis的用法,並實現了簡單的封裝

那麼,先給出幾個參考資料吧

關於兩種快取:https://www.cnblogs.com/yuangang/p/5800113.html

關於redis持久化:https://blog.csdn.net/u010785685/article/details/52366977

兩個nuget包,不用多說

接下來,貼出程式碼

首先在startup,我讀取了appstting.json的資料,作為redis的配置

複製程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Application.Common;
using Application.Common.CommonObject;
using Application.CoreWork;
using Application.DAL;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Application.web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            Connection.MySqlConnection = Configuration.GetConnectionString("MySqlConnection");
            Connection.SqlConnection = Configuration.GetConnectionString("SqlConnection");
            RedisConfig.Connection = Configuration.GetSection("RedisConfig")["Connection"];
            RedisConfig.DefaultDatabase =Convert.ToInt32( Configuration.GetSection("RedisConfig")["DefaultDatabase"]);
            RedisConfig.InstanceName = Configuration.GetSection("RedisConfig")["InstanceName"];
            CommonManager.CacheObj.GetMessage<RedisCacheHelper>();
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
複製程式碼

再貼上配置

1 2 3 4 5 "RedisConfig"
: {          "Connection" "127.0.0.1:6379" ,          "DefaultDatabase" : 0,          "InstanceName" "Redis1"      },

  

用來放配置資訊的靜態類

複製程式碼
using System;
using System.Collections.Generic;
using System.Text;

namespace Application.Common
{
    public static class RedisConfig
    {
        public static string configname { get; set; }
        public static string Connection { get; set; }
        public static int DefaultDatabase { get; set; }
        public static string InstanceName { get; set; }
    }
}
複製程式碼

然後ICacheHelper.cs,這個類是兩種快取通用的介面,讓使用更方便

複製程式碼
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace Application.Common.CommonObject
{
    public interface ICacheHelper
    {
        bool Exists(string key);


        T GetCache<T>(string key) where T : class;


        void SetCache(string key, object value);


        void SetCache(string key, object value, DateTimeOffset expiressAbsoulte);//設定絕對時間過期


        void SetSlidingCache(string key, object value, TimeSpan t);  //設定滑動過期, 因redis暫未找到自帶的滑動過期類的API,暫無需實現該介面


        void RemoveCache(string key);

        void KeyMigrate(string key, EndPoint endPoint,int database,int timeountseconds);

        void Dispose();

        void GetMssages();

        void Publish(string msg);
    }
}
複製程式碼

然後,實現介面,首先是MemoryCacheHelper

複製程式碼
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace Application.Common.CommonObject
{
    public class MemoryCacheHelper : ICacheHelper
    {
        //public MemoryCacheHelper(/*MemoryCacheOptions options*/)//這裡可以做成依賴注入,但沒打算做成通用類庫,所以直接把選項直接封在幫助類裡邊
        //{
        //    //this._cache = new MemoryCache(options);
        //    //this._cache = new MemoryCache(new MemoryCacheOptions());
        //}
        //public MemoryCacheHelper(MemoryCacheOptions options)//這裡可以做成依賴注入,但沒打算做成通用類庫,所以直接把選項直接封在幫助類裡邊
        //{
        //    this._cache = new MemoryCache(options);
        //}

        public static IMemoryCache _cache=new MemoryCache(new MemoryCacheOptions());

        /// <summary>
        /// 是否存在此快取
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Exists(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            object v = null;
            return _cache.TryGetValue<object>(key, out v);
        }
        /// <summary>
        /// 取得快取資料
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T GetCache<T>(string key) where T : class
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));


            T v = null;
            _cache.TryGetValue<T>(key, out v);


            return v;
        }
        /// <summary>
        /// 設定快取
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SetCache(string key, object value)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));


            object v = null;
            if (_cache.TryGetValue(key, out v))
                _cache.Remove(key);
            _cache.Set<object>(key, value);
        }
        /// <summary>
        /// 設定快取,絕對過期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expirationMinute">間隔分鐘</param>
        /// CommonManager.CacheObj.Save<RedisCacheHelper>("test", "RedisCache works!", 30);
        public void SetCache(string key, object value, double expirationMinute)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            object v = null;
            if (_cache.TryGetValue(key, out v))
                _cache.Remove(key);
            DateTime now = DateTime.Now;
            TimeSpan ts = now.AddMinutes(expirationMinute) - DateTime.Now;
            _cache.Set<object>(key, value, ts);
        }
        /// <summary>
        /// 設定快取,絕對過期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expirationTime">DateTimeOffset 結束時間</param>
        /// CommonManager.CacheObj.Save<RedisCacheHelper>("test", "RedisCache works!", DateTimeOffset.Now.AddSeconds(30));
        public void SetCache(string key, object value, DateTimeOffset expirationTime)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            object v = null;
            if (_cache.TryGetValue(key, out v))
                _cache.Remove(key);

            _cache.Set<object>(key, value, expirationTime);
        }
        /// <summary>
        /// 設定快取,相對過期時間
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="t"></param>
        /// CommonManager.CacheObj.SaveSlidingCache<MemoryCacheHelper>("test", "MemoryCache works!",TimeSpan.FromSeconds(30));
        public void SetSlidingCache(string key,object value,TimeSpan t)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            object v = null;
            if (_cache.TryGetValue(key, out v))
                _cache.Remove(key);

            _cache.Set(key, value, new MemoryCacheEntryOptions()
            {
                SlidingExpiration=t
            });
        }
        /// <summary>
        /// 移除快取
        /// </summary>
        /// <param name="key"></param>
        public void RemoveCache(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));

            _cache.Remove(key);
        }

        /// <summary>
        /// 釋放
        /// </summary>
        public void Dispose()
        {
            if (_cache != null)
                _cache.Dispose();
            GC.SuppressFinalize(this);
        }

        public void KeyMigrate(string key, EndPoint endPoint, int database, int timeountseconds)
        {
            throw new NotImplementedException();
        }

        public void GetMssages()
        {
            throw new NotImplementedException();
        }

        public void Publish(string msg)
        {
            throw new NotImplementedException();
        }
    }
}
複製程式碼

然後是RedisCacheHelper

複製程式碼
using Microsoft.Extensions.Caching.Redis;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace Application.Common.CommonObject
{
    public class RedisCacheHelper : ICacheHelper
    {
        public RedisCacheHelper(/*RedisCacheOptions options, int database = 0*/)//這裡可以做成依賴注入,但沒打算做成通用類庫,所以直接把連線資訊直接寫在幫助類裡
        {
            options = new RedisCacheOptions();
            options.Configuration = "127.0.0.1:6379";//RedisConfig.Connection;
            options.InstanceName = RedisConfig.InstanceName;
            int database = RedisConfig.DefaultDatabase;
            _connection = ConnectionMultiplexer.Connect(options.Configuration);
            _cache = _connection.GetDatabase(database);
            _instanceName = options.InstanceName;
            _sub = _connection.GetSubscriber();
        }

        public static RedisCacheOptions options;
        public static IDatabase _cache;

        public static ConnectionMultiplexer _connection;

        public static string _instanceName;

        public static ISubscriber _sub;

        /// <summary>
        /// 取得redis的Key名稱
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private string GetKeyForRedis(string key)
        {
            return _instanceName + key;
        }
        /// <summary>
        /// 判斷當前Key是否存在資料
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Exists(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            return _cache.KeyExists(GetKeyForRedis(key));
        }

        /// <summary>
        /// 取得快取資料
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T GetCache<T>(string key) where T : class
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            var value = _cache.StringGet(GetKeyForRedis(key));
            if (!value.HasValue)
                return default(T);
            return JsonConvert.DeserializeObject<T>(value);
        }
        /// <summary>
        /// 設定快取資料
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SetCache(string key, object value)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            if (Exists(GetKeyForRedis(key)))
                RemoveCache(GetKeyForRedis(key));

            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value));
        }
        /// <summary>
        /// 設定絕對過期時間
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiressAbsoulte"></param>
        public void SetCache(string key, object value, DateTimeOffset expiressAbsoulte)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            if (Exists(GetKeyForRedis(key)))
                RemoveCache(GetKeyForRedis(key));
            TimeSpan t = expiressAbsoulte - DateTimeOffset.Now;
            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value), t);
        }
        /// <summary>
        /// 設定相對過期時間
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expirationMinute"></param>
        public void SetCache(string key, object value, double expirationMinute)
        {
            if (Exists(GetKeyForRedis(key)))
                RemoveCache(GetKeyForRedis(key));

            DateTime now = DateTime.Now;
            TimeSpan ts = now.AddMinutes(expirationMinute) - now;
            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value), ts);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="endPoint"></param>
        /// <param name="database"></param>
        /// <param name="timeountseconds"></param>
        public void KeyMigrate(string key, EndPoint endPoint, int database, int timeountseconds) {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            _cache.KeyMigrate(GetKeyForRedis(key), endPoint, database, timeountseconds);
        }
        /// <summary>
        /// 移除redis
        /// </summary>
        /// <param name="key"></param>
        public void RemoveCache(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));

            _cache.KeyDelete(GetKeyForRedis(key));
        }

        /// <summary>
        /// 銷燬連線
        /// </summary>
        public void Dispose()
        {
            if (_connection != null)
                _connection.Dispose();
            GC.SuppressFinalize(this);
        }

        public void SetSlidingCache(string key, object value, TimeSpan t)
        {
            throw new NotImplementedException();
        }

        public void GetMssages()
        {
            using (_connection = ConnectionMultiplexer.Connect(options.Configuration))
                _sub.Subscribe("msg", (channel, message) =>
                {
                    string result = message;
                });
        }

        public void Publish(string msg)
        {
            using (_connection=ConnectionMultiplexer.Connect(options.Configuration))
                _sub.Publish("msg", msg);
        }
    }
}
複製程式碼

然後是Cache.cs,用來例項化,此處用單例模式,保證專案使用的是一個快取例項,博主吃過虧,由於redis例項過多,建構函式執行太多次,導致client連線數過大,記憶體不夠跑,速度卡慢

複製程式碼
using System;
using System.Collections.Generic;
using System.Text;

namespace Application.Common.CommonObject
{
    public sealed class Cache
    {
        internal Cache() { }
        public static ICacheHelper cache;
        /// <summary>
        /// 判斷快取是否存在
        /// </summary>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">鍵名</param>
        /// <returns></returns>
        public bool Exists<CacheType>(string key) where CacheType : ICacheHelper, new()
        {
            if (cache!=null&& typeof(CacheType).Equals(cache.GetType()))
                return cache.Exists(key);
            else
            {
                cache = new CacheType();
                return cache.Exists(key);
            }
        }

        /// <summary>
        /// 獲取快取
        /// </summary>
        /// <typeparam name="T">轉換的類</typeparam>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">鍵名</param>
        /// <returns>轉換為T型別的值</returns>
        public T GetCache<T,CacheType>(string key)
            where T:class
            where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                return cache.GetCache<T>(key);
            else
            {
                cache = new CacheType();
                return cache.GetCache<T>(key);
            }
        }

        /// <summary>
        /// 儲存快取
        /// </summary>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">鍵名</param>
        /// <param name="value">值</param>
        public void Save<CacheType>(string key,object value) where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.SetCache(key, value);
            else
            {
                cache = new CacheType();
                cache.SetCache(key, value);
            }
        }

        /// <summary>
        /// 儲存快取並設定絕對過期時間
        /// </summary>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">鍵名</param>
        /// <param name="value">值</param>
        /// <param name="expiressAbsoulte">絕對過期時間</param>
        public void Save<CacheType>(string key, object value, DateTimeOffset expiressAbsoulte) where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.SetCache(key, value, expiressAbsoulte);
            else
            {
                cache = new CacheType();
                cache.SetCache(key, value, expiressAbsoulte);
            }
        }

        /// <summary>
        /// 儲存滑動快取
        /// </summary>
        /// <typeparam name="CacheType">只能用memorycache,redis暫不實現</typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="t">間隔時間</param>
        public void SaveSlidingCache<CacheType>(string key, object value,TimeSpan t) where CacheType : MemoryCacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.SetSlidingCache(key, value, t);
            else
            {
                cache = new CacheType();
                cache.SetSlidingCache(key, value, t);
            }
        }

        /// <summary>
        /// 刪除一個快取
        /// </summary>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">要刪除的key</param>
        public void Delete<CacheType>(string key)where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.RemoveCache(key);
            else
            {
                cache = new CacheType();
                cache.RemoveCache(key);
            }
        }

        /// <summary>
        /// 釋放
        /// </summary>
        /// <typeparam name="CacheType"></typeparam>
        public void Dispose<CacheType>() where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.Dispose();
            else
            {
                cache = new CacheType();
                cache.Dispose();
            }
        }

        public void GetMessage<CacheType>() where CacheType:RedisCacheHelper,new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.GetMssages();
            else
            {
                cache = new CacheType();
                cache.GetMssages();
            }
        }

        public void Publish<CacheType>(string msg)where CacheType : RedisCacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.Publish(msg);
            else
            {
                cache = new CacheType();
                cache.Publish(msg);
            }
        }
    }
}
複製程式碼

接下來,CommonManager.cs,該類主要是為了作為一個靜態類呼叫快取,由於Cache.cs並非靜態類,方便呼叫

複製程式碼
using Application.Common.CommonObject;
using System;
using System.Collections.Generic;
using System.Text;

namespace Application.Common
{
    public class CommonManager
    {
        private static readonly object lockobj = new object();
        private static volatile Cache _cache = null;
        /// <summary>
        /// Cache
        /// </summary>
        public static Cache CacheObj
        {
            get
            {
                if (_cache == null)
                {
                    lock (lockobj)
                    {
                        if (_cache == null)
                            _cache = new Cache();
                    }
                }
                return _cache;
            }
        }
    }
}
複製程式碼

最後呢就是使用啦隨便建的一個控制器

複製程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Application.Common;
using Application.Common.CommonObject;
using Application.CoreWork;
using Microsoft.AspNetCore.Mvc;

namespace Application.web.Controllers
{
    public class DefaultController : BaseController
    {
        public IActionResult Index()
        {
            for (int i = 0; i < 100000; i++)
            {
                CommonManager.CacheObj.Save<RedisCacheHelper>("key" + i, "key" + i + " works!");
            }
            return View();
        }

        public IActionResult GetStrin(int index)
        {
            string res = "已經過期了";
            if (CommonManager.CacheObj.Exists<RedisCacheHelper>("key" + index))
            {
                res = CommonManager.CacheObj.GetCache<String, RedisCacheHelper>("key" + index);
            }
            return Json(new ExtJson { success = true, code = 1000, msg = "成功", jsonresult = res });
        }

        public IActionResult Publish(string msg)
        {
            try
            {
                CommonManager.CacheObj.Publish<RedisCacheHelper>(msg);
                return Json(new ExtJson { success = true, code = 1000, msg = "成功", jsonresult = msg });
            }
            catch
            {
                return Json(new ExtJson
                {
                    success = true,
                    code = 1000,
                    msg = "失敗",
                    jsonresult = msg
                });
            }
        }
    }
}
複製程式碼

那麼,有的朋友在json處可能會報錯,自己封裝下,或者用原來的json吧

如果有不懂的地方,可以在評論中提問,有更好的改進方式,也請聯絡我,共同進步,感謝閱讀

 

自從使用Asp.net Core2.0 以來,不停摸索,查閱資料,這方面的資料是真的少,因此,在前人的基礎上,摸索出了Asp.net Core2.0 快取 MemoryCache 和 Redis的用法,並實現了簡單的封裝

那麼,先給出幾個參考資料吧

關於兩種快取:https://www.cnblogs.com/yuangang/p/5800113.html

關於redis持久化:https://blog.csdn.net/u010785685/article/details/52366977

兩個nuget包,不用多說

接下來,貼出程式碼

首先在startup,我讀取了appstting.json的資料,作為redis的配置

複製程式碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Application.Common;
using Application.Common.CommonObject;
using Application.CoreWork;
using Application.DAL;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Application.web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            Connection.MySqlConnection = Configuration.GetConnectionString("MySqlConnection");
            Connection.SqlConnection = Configuration.GetConnectionString("SqlConnection");
            RedisConfig.Connection = Configuration.GetSection("RedisConfig")["Connection"];
            RedisConfig.DefaultDatabase =Convert.ToInt32( Configuration.GetSection("RedisConfig")["DefaultDatabase"]);
            RedisConfig.InstanceName = Configuration.GetSection("RedisConfig")["InstanceName"];
            CommonManager.CacheObj.GetMessage<RedisCacheHelper>();
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
複製程式碼

再貼上配置

1 2 3 4 5 "RedisConfig" : {          "Connection" "127.0.0.1:6379" ,          "DefaultDatabase" : 0,          "InstanceName" "Redis1"      },

  

用來放配置資訊的靜態類

複製程式碼
using System;
using System.Collections.Generic;
using System.Text;

namespace Application.Common
{
    public static class RedisConfig
    {
        public static string configname { get; set; }
        public static string Connection { get; set; }
        public static int DefaultDatabase { get; set; }
        public static string InstanceName { get; set; }
    }
}
複製程式碼

然後ICacheHelper.cs,這個類是兩種快取通用的介面,讓使用更方便

複製程式碼
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace Application.Common.CommonObject
{
    public interface ICacheHelper
    {
        bool Exists(string key);


        T GetCache<T>(string key) where T : class;


        void SetCache(string key, object value);


        void SetCache(string key, object value, DateTimeOffset expiressAbsoulte);//設定絕對時間過期


        void SetSlidingCache(string key, object value, TimeSpan t);  //設定滑動過期, 因redis暫未找到自帶的滑動過期類的API,暫無需實現該介面


        void RemoveCache(string key);

        void KeyMigrate(string key, EndPoint endPoint,int database,int timeountseconds);

        void Dispose();

        void GetMssages();

        void Publish(string msg);
    }
}
複製程式碼

然後,實現介面,首先是MemoryCacheHelper

複製程式碼
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace Application.Common.CommonObject
{
    public class MemoryCacheHelper : ICacheHelper
    {
        //public MemoryCacheHelper(/*MemoryCacheOptions options*/)//這裡可以做成依賴注入,但沒打算做成通用類庫,所以直接把選項直接封在幫助類裡邊
        //{
        //    //this._cache = new MemoryCache(options);
        //    //this._cache = new MemoryCache(new MemoryCacheOptions());
        //}
        //public MemoryCacheHelper(MemoryCacheOptions options)//這裡可以做成依賴注入,但沒打算做成通用類庫,所以直接把選項直接封在幫助類裡邊
        //{
        //    this._cache = new MemoryCache(options);
        //}

        public static IMemoryCache _cache=new MemoryCache(new MemoryCacheOptions());

        /// <summary>
        /// 是否存在此快取
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Exists(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            object v = null;
            return _cache.TryGetValue<object>(key, out v);
        }
        /// <summary>
        /// 取得快取資料
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T GetCache<T>(string key) where T : class
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));


            T v = null;
            _cache.TryGetValue<T>(key, out v);


            return v;
        }
        /// <summary>
        /// 設定快取
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SetCache(string key, object value)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));


            object v = null;
            if (_cache.TryGetValue(key, out v))
                _cache.Remove(key);
            _cache.Set<object>(key, value);
        }
        /// <summary>
        /// 設定快取,絕對過期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expirationMinute">間隔分鐘</param>
        /// CommonManager.CacheObj.Save<RedisCacheHelper>("test", "RedisCache works!", 30);
        public void SetCache(string key, object value, double expirationMinute)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            object v = null;
            if (_cache.TryGetValue(key, out v))
                _cache.Remove(key);
            DateTime now = DateTime.Now;
            TimeSpan ts = now.AddMinutes(expirationMinute) - DateTime.Now;
            _cache.Set<object>(key, value, ts);
        }
        /// <summary>
        /// 設定快取,絕對過期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expirationTime">DateTimeOffset 結束時間</param>
        /// CommonManager.CacheObj.Save<RedisCacheHelper>("test", "RedisCache works!", DateTimeOffset.Now.AddSeconds(30));
        public void SetCache(string key, object value, DateTimeOffset expirationTime)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            object v = null;
            if (_cache.TryGetValue(key, out v))
                _cache.Remove(key);

            _cache.Set<object>(key, value, expirationTime);
        }
        /// <summary>
        /// 設定快取,相對過期時間
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="t"></param>
        /// CommonManager.CacheObj.SaveSlidingCache<MemoryCacheHelper>("test", "MemoryCache works!",TimeSpan.FromSeconds(30));
        public void SetSlidingCache(string key,object value,TimeSpan t)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            object v = null;
            if (_cache.TryGetValue(key, out v))
                _cache.Remove(key);

            _cache.Set(key, value, new MemoryCacheEntryOptions()
            {
                SlidingExpiration=t
            });
        }
        /// <summary>
        /// 移除快取
        /// </summary>
        /// <param name="key"></param>
        public void RemoveCache(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));

            _cache.Remove(key);
        }

        /// <summary>
        /// 釋放
        /// </summary>
        public void Dispose()
        {
            if (_cache != null)
                _cache.Dispose();
            GC.SuppressFinalize(this);
        }

        public void KeyMigrate(string key, EndPoint endPoint, int database, int timeountseconds)
        {
            throw new NotImplementedException();
        }

        public void GetMssages()
        {
            throw new NotImplementedException();
        }

        public void Publish(string msg)
        {
            throw new NotImplementedException();
        }
    }
}
複製程式碼

然後是RedisCacheHelper

複製程式碼
using Microsoft.Extensions.Caching.Redis;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace Application.Common.CommonObject
{
    public class RedisCacheHelper : ICacheHelper
    {
        public RedisCacheHelper(/*RedisCacheOptions options, int database = 0*/)//這裡可以做成依賴注入,但沒打算做成通用類庫,所以直接把連線資訊直接寫在幫助類裡
        {
            options = new RedisCacheOptions();
            options.Configuration = "127.0.0.1:6379";//RedisConfig.Connection;
            options.InstanceName = RedisConfig.InstanceName;
            int database = RedisConfig.DefaultDatabase;
            _connection = ConnectionMultiplexer.Connect(options.Configuration);
            _cache = _connection.GetDatabase(database);
            _instanceName = options.InstanceName;
            _sub = _connection.GetSubscriber();
        }

        public static RedisCacheOptions options;
        public static IDatabase _cache;

        public static ConnectionMultiplexer _connection;

        public static string _instanceName;

        public static ISubscriber _sub;

        /// <summary>
        /// 取得redis的Key名稱
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private string GetKeyForRedis(string key)
        {
            return _instanceName + key;
        }
        /// <summary>
        /// 判斷當前Key是否存在資料
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Exists(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            return _cache.KeyExists(GetKeyForRedis(key));
        }

        /// <summary>
        /// 取得快取資料
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T GetCache<T>(string key) where T : class
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            var value = _cache.StringGet(GetKeyForRedis(key));
            if (!value.HasValue)
                return default(T);
            return JsonConvert.DeserializeObject<T>(value);
        }
        /// <summary>
        /// 設定快取資料
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SetCache(string key, object value)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            if (Exists(GetKeyForRedis(key)))
                RemoveCache(GetKeyForRedis(key));

            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value));
        }
        /// <summary>
        /// 設定絕對過期時間
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expiressAbsoulte"></param>
        public void SetCache(string key, object value, DateTimeOffset expiressAbsoulte)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            if (value == null)
                throw new ArgumentNullException(nameof(value));

            if (Exists(GetKeyForRedis(key)))
                RemoveCache(GetKeyForRedis(key));
            TimeSpan t = expiressAbsoulte - DateTimeOffset.Now;
            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value), t);
        }
        /// <summary>
        /// 設定相對過期時間
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expirationMinute"></param>
        public void SetCache(string key, object value, double expirationMinute)
        {
            if (Exists(GetKeyForRedis(key)))
                RemoveCache(GetKeyForRedis(key));

            DateTime now = DateTime.Now;
            TimeSpan ts = now.AddMinutes(expirationMinute) - now;
            _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value), ts);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="endPoint"></param>
        /// <param name="database"></param>
        /// <param name="timeountseconds"></param>
        public void KeyMigrate(string key, EndPoint endPoint, int database, int timeountseconds) {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));
            _cache.KeyMigrate(GetKeyForRedis(key), endPoint, database, timeountseconds);
        }
        /// <summary>
        /// 移除redis
        /// </summary>
        /// <param name="key"></param>
        public void RemoveCache(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
                throw new ArgumentNullException(nameof(key));

            _cache.KeyDelete(GetKeyForRedis(key));
        }

        /// <summary>
        /// 銷燬連線
        /// </summary>
        public void Dispose()
        {
            if (_connection != null)
                _connection.Dispose();
            GC.SuppressFinalize(this);
        }

        public void SetSlidingCache(string key, object value, TimeSpan t)
        {
            throw new NotImplementedException();
        }

        public void GetMssages()
        {
            using (_connection = ConnectionMultiplexer.Connect(options.Configuration))
                _sub.Subscribe("msg", (channel, message) =>
                {
                    string result = message;
                });
        }

        public void Publish(string msg)
        {
            using (_connection=ConnectionMultiplexer.Connect(options.Configuration))
                _sub.Publish("msg", msg);
        }
    }
}
複製程式碼

然後是Cache.cs,用來例項化,此處用單例模式,保證專案使用的是一個快取例項,博主吃過虧,由於redis例項過多,建構函式執行太多次,導致client連線數過大,記憶體不夠跑,速度卡慢

複製程式碼
using System;
using System.Collections.Generic;
using System.Text;

namespace Application.Common.CommonObject
{
    public sealed class Cache
    {
        internal Cache() { }
        public static ICacheHelper cache;
        /// <summary>
        /// 判斷快取是否存在
        /// </summary>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">鍵名</param>
        /// <returns></returns>
        public bool Exists<CacheType>(string key) where CacheType : ICacheHelper, new()
        {
            if (cache!=null&& typeof(CacheType).Equals(cache.GetType()))
                return cache.Exists(key);
            else
            {
                cache = new CacheType();
                return cache.Exists(key);
            }
        }

        /// <summary>
        /// 獲取快取
        /// </summary>
        /// <typeparam name="T">轉換的類</typeparam>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">鍵名</param>
        /// <returns>轉換為T型別的值</returns>
        public T GetCache<T,CacheType>(string key)
            where T:class
            where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                return cache.GetCache<T>(key);
            else
            {
                cache = new CacheType();
                return cache.GetCache<T>(key);
            }
        }

        /// <summary>
        /// 儲存快取
        /// </summary>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">鍵名</param>
        /// <param name="value">值</param>
        public void Save<CacheType>(string key,object value) where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.SetCache(key, value);
            else
            {
                cache = new CacheType();
                cache.SetCache(key, value);
            }
        }

        /// <summary>
        /// 儲存快取並設定絕對過期時間
        /// </summary>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">鍵名</param>
        /// <param name="value">值</param>
        /// <param name="expiressAbsoulte">絕對過期時間</param>
        public void Save<CacheType>(string key, object value, DateTimeOffset expiressAbsoulte) where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.SetCache(key, value, expiressAbsoulte);
            else
            {
                cache = new CacheType();
                cache.SetCache(key, value, expiressAbsoulte);
            }
        }

        /// <summary>
        /// 儲存滑動快取
        /// </summary>
        /// <typeparam name="CacheType">只能用memorycache,redis暫不實現</typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="t">間隔時間</param>
        public void SaveSlidingCache<CacheType>(string key, object value,TimeSpan t) where CacheType : MemoryCacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.SetSlidingCache(key, value, t);
            else
            {
                cache = new CacheType();
                cache.SetSlidingCache(key, value, t);
            }
        }

        /// <summary>
        /// 刪除一個快取
        /// </summary>
        /// <typeparam name="CacheType">快取型別</typeparam>
        /// <param name="key">要刪除的key</param>
        public void Delete<CacheType>(string key)where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.RemoveCache(key);
            else
            {
                cache = new CacheType();
                cache.RemoveCache(key);
            }
        }

        /// <summary>
        /// 釋放
        /// </summary>
        /// <typeparam name="CacheType"></typeparam>
        public void Dispose<CacheType>() where CacheType : ICacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.Dispose();
            else
            {
                cache = new CacheType();
                cache.Dispose();
            }
        }

        public void GetMessage<CacheType>() where CacheType:RedisCacheHelper,new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.GetMssages();
            else
            {
                cache = new CacheType();
                cache.GetMssages();
            }
        }

        public void Publish<CacheType>(string msg)where CacheType : RedisCacheHelper, new()
        {
            if (cache != null && typeof(CacheType).Equals(cache.GetType()))
                cache.Publish(msg);
            else
            {
                cache = new CacheType();
                cache.Publish(msg);
            }
        }
    }
}
複製程式碼

接下來,CommonManager.cs,該類主要是為了作為一個靜態類呼叫快取,由於Cache.cs並非靜態類,方便呼叫

相關推薦

Asp.net Core2.0 快取 MemoryCache Redis

    自從使用Asp.net Core2.0 以來,不停摸索,查閱資料,這方面的資料是真的少,因此,在前人的基礎上,摸索出了Asp.net Core2.0 快取 MemoryCache 和 Redis的用法,並實現了簡單的封裝 那麼,先給出幾個參考

Asp.net Core 快取 MemoryCache Redis

https://blog.csdn.net/warrior21st/article/details/62884629 快取介面 ICacheService      快取也好,資料庫也好,我們就是進行CRUD操作,介面沒什麼好解釋的,註釋我寫的很明白,這裡就

【無私分享:ASP.NET CORE 專案實戰(第十一章)】Asp.net Core 快取 MemoryCache Redis

1 /// <summary> 2 /// 修改快取 3 /// </summary> 4 /// <param name="key">快取Key</param> 5 ///

ASP.NET 2.0 快取過期、連線池

問:使用 .js 和級聯樣式表 (CSS) include 時是否有什麼技巧,以便對它們進行快取,而不必在每次發出請求時都進行提取?答:為了實現這種型別的快取,您可以使用 IIS 管理單元中的 HTTP 標頭屬性表,通過選中“啟用內容過期”複選框來啟用內容過期。這樣會使用 E

WebApi遷移ASP.NET Core2.0

content .config true 進入 服務 設置 網關 系統 win WebApi遷移ASP.NET Core2.0 一步一步帶你做WebApi遷移ASP.NET Core2.0 隨著ASP.NET Core 2.0發布之後,原先運行在Windows II

Asp.NET Core2.0 項目實戰入門視頻課程_完整版

第5章 frame 封裝 今天 使用 結束 技巧 標題 技術分享 END OR START? 看到這個標題,你開不開心,激不激動呢? 沒錯,.net core的入門課程已經完畢了。52ABP.School項目從11月19日,第一章視頻的試錄制,到今天完整版出爐,離不開各位的

asp.net core1.x/asp.net core2.0中如何加載多個配置文件

加載 自己 團隊 多配置文件 做的 ted 文章 pos 簡單 寫這篇文章,來簡單的談一下,asp.net core中,如何加載多配置文件,如有錯誤請斧正。 在1.x的時候,我們是自己配置 WebHostBuilder而在2.0的時候,ef core團隊,將配置寫到了

用VSCode開發一個asp.net core2.0+angular5項目(5): Angular5+asp.net core 2.0 web api文件上傳

owb bus sed loaded runt ace created one 做了 第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 第二部分: http://www.cnblogs.com/cgzl/p/8481825.

asp.net core2.0專案部署在IIS上執行

與ASP.NET時代不同,ASP.NET Core不再是由IIS工作程序(w3wp.exe)託管,而是獨立執行的。它獨立執行在控制檯應用程式中,並通過dotnet執行時命令呼叫。它並沒有被載入到IIS工作程序中,但是IIS卻載入了名為AspNetCoreModule的

3、ASP.Net Core2.0值Filter

        Asp.Net Core的filter總共有5種,它們分別是Authorization Filter(授權過濾器)、Resource Filter(資源過濾器),Action Filter、Exception Filter(異常過濾器)和Result Filt

【翻譯】asp.net core2.0中的token認證

原文地址:https://developer.okta.com/blog/2018/03/23/token-authentication-aspnetcore-complete-guide token認證在最近幾年正在成為一個流行的主題,特別是隨著移動應用和js應用不斷的獲得關注。像OAuth 2.0和Op

在阿里雲Windows Server 上部署ASP .NET CORE2.0專案

近期使用ASP.NET Core2.0對部落格進行了重寫,在部署到伺服器時遇到了一些問題,來記錄一下留用。 配置環境 安裝 .Net Framework3.5 在IIS管理器上直接開啟,這裡總是失敗,上網上找了找,發現了可以使用命令列安裝,開啟Pow

core學習歷程五 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析:簡單日誌記錄 + 服務切面快取 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十一 || AOP自定義篩選,Redis入門 11.1

繼續學習 “老張的哲學”博主的系列教程,感謝大神們的無私分享 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析:簡單日誌記錄 + 服務切面快取 說是朦朧,,emmm,對我來說是迷糊哈。上半段正常,下半段有點難理解,操作是沒問題。多看幾遍再消

基於Asp.net Core 3.1實現的RedisMemoryCache快取助手CacheHelper

這幾天在面試,這個關於Redis快取的部落格一直沒空寫,今天總算有點時間了。   從很久很久之前,我就一直想學Redis了,反正看到各大招聘網上都要求Redis,不學就太落後了。 一開始我是按微軟官網文件那樣配置的,然後發現這也太簡單了,不止配置簡單,連使用都這麼簡單,簡單得有點過分。如下圖所示,它

Asp.Net Core 2.0 項目實戰(2)NCMVC一個基於Net Core2.0搭建的角色權限管理開發框架

ML 用戶 解密 https redis json uil AI 不足 本文目錄 1. 摘要 2. 框架介紹 3. 權限管理之多一點說明 4. 總結 1. 摘要   NCMVC角色權限管理框架是由最近練習Net Core時抽時間整理的

asp.net core2.1中新增中介軟體以擴充套件Swashbuckle.AspNetCore3.0支援簡單的文件訪問許可權控制

Swashbuckle.AspNetCore3.0 介紹 一個使用 ASP.NET Core 構建的 API 的 Swagger 工具。直接從您的路由,控制器和模型生成漂亮的 API 文件,包括用於探索和測試操作的 UI。 專案主頁:https://github.com/domaindrivendev/Sw

從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析:簡單日誌記錄 + 服務切面快取

  今天的講解就到了這裡了,通過這兩個小栗子,大家應該能對面向切面程式設計有一些朦朧的感覺了吧

從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十一 || AOP自定義篩選,Redis入門 11.1

大神留步 先說下一個窩心的問題,求大神幫忙,如何在AOP中去使用泛型,有償幫助,這裡謝謝,文末有詳細問題說明,可以留言或者私信都可以。 當然我也會一直思考,大家持續關注本帖,如果我想到好辦法,會及時更新,並通知大家。 程式碼已上傳Github+Gitee,文末有地址   傳統的快取是在Co

解決 web伺服器部署常見問題,server application unavailable 程式無法連線資料庫 的問題(asp.net 2.0 + oracle9i + winXP)

部署時出現以下錯誤: server application unavailable the web application you are attempting to access on this web server is currently unavailable. pl

asp.net ajax asp.net 2.0中的fileupload合力打造無重新整理檔案上傳控制元件

{20        bool fileOK =false;21        //獲取根檔案絕對路徑22string path = Server.MapPath("~/UpLoad/");23        //如上傳了檔案,就判斷檔案格式24        FileUpload FU = FileUplo