System.Runtime.Caching.MemoryCache 缓存应用实践
需求:将高频且耗时,且数据基本没变化的查询结果,用缓存提升性能。
实现:继承MemoryCache,重载部分方法,在数据库中持久化缓存数据。
本文使用了两级缓存,不用考虑缓存加载。服务重启,读不到内存缓存,会从数据库读取一次。
//泛型类,内部进行二进制序列化与反序列化 using System; using System.Collections.Specialized; using System.IO; using System.Runtime.Caching; using System.Runtime.Serialization.Formatters.Binary; namespace xxx.BLL { public class DBTCache<T> : MemoryCache where T : class, new() { public DBTCache(string name, NameValueCollection config = null) : base(name, config) { } public override bool Add(string key, object value, DateTimeOffset dtime, string regionName = null) { var mem = new MemoryStream(); new BinaryFormatter().Serialize(mem, value); if (base.Contains(key)) base.Set(key, mem.GetBuffer(), dtime, regionName); else base.Add(key, mem.GetBuffer(), dtime, regionName); var data = new Model.__Cache() { sKey = key, vObj = mem.GetBuffer(), dTime = dtime.DateTime }; mem.Dispose(); return DB.Update(data) || DB.Insert(data); } public override object Get(string key, string regionName = null) { if (!base.Contains(key, regionName)) { var cache = DB.GetFirst(t => t.sKey == key); if (cache is null) return null; else base.Add(key, cache.vObj, cache.dTime, regionName); } return new BinaryFormatter().Deserialize(new MemoryStream((byte[])base.Get(key, regionName))) as T; //return base.Get(key, regionName); } public bool Clear() { DB.Context.DbMaintenance.TruncateTable("__Cache"); base.Trim(100); return true; } private static DAL.IEntity<Model.__Cache> _db = null; private DAL.IEntity<Model.__Cache> DB { get { if (_db is null) _db = new DAL.IEntity<Model.__Cache>(); return _db; } } } }
//调用 static DBTCache<List<PowerData>> cache = new DBTCache<List<PowerData>>("xxxsssssxxxx"); return cache.Get(key) as List<PowerData>; //get cache.Add(key, ListTData, DateTime.Now.AddDays(1)); //add
另一个通用版本: add/get需要在调用时反/序列化
using System; using System.Collections.Specialized; using System.Runtime.Caching; namespace xxx.BLL { public class DBCache : MemoryCache { public DBCache(string name, NameValueCollection config = null) : base(name, config) { } public override bool Add(string key, object value, DateTimeOffset dtime, string regionName = null) { if (base.Contains(key)) base.Set(key, value, dtime, regionName); else base.Add(key, value, dtime, regionName); var data = new Model.__Cache() { sKey = key, vObj = (byte[])value, dTime = dtime.DateTime }; return DB.Update(data) || DB.Insert(data); } public override object Get(string key, string regionName = null) { if (!base.Contains(key, regionName)) { var cache = DB.GetFirst(t => t.sKey == key); if (cache is null) return null; else base.Add(key, cache.vObj, cache.dTime, regionName); } return base.Get(key, regionName); } public bool Clear() { DB.Context.DbMaintenance.TruncateTable("__Cache"); base.Trim(100); return true; } private static DAL.IEntity<Model.__Cache> _db = null; private DAL.IEntity<Model.__Cache> DB { get { if (_db is null) _db = new DAL.IEntity<Model.__Cache>(); return _db; } } } } //调用 //static DBCache cache = new DBCache("asfasdafsdafda"); //return new BinaryFormatter().Deserialize(new MemoryStream((byte[])obj)) as List<PowerData>; //var mem = new MemoryStream(); //new BinaryFormatter().Serialize(mem, data); //cache.Add(key, mem.GetBuffer(), DateTime.Now.AddDays(1)); //mem.Dispose();