.NetCore 内置缓存加入到EFCore操作中,数据更新或者查询时自动更新缓存。
2019-04-27
初步完成逻辑代码编写,尚未经过测试,诸多细节有待完善。
2019-04-28
简单功能测试及部分错误逻辑修改。
using Microsoft.EntityFrameworkCore;using Microsoft.Extensions.Caching.Memory;using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;namespace FXY_NetCore_DbContext{ public class DefaultContext { ////// a queue to save the handle,if will be empted when call savechanges(). /// private ConcurrentQueueCacheQueue { get; set; } /// /// databse context. /// private DbContext Context { get; set; } ////// netocre inner cache. /// private IMemoryCache Cache { get; set; } ////// the time of cache's life cycle /// private int ExpirtTime { get; set; } = 10; ////// entity context. /// /// database context /// cache /// expirt time,default 60 sencond. public DefaultContext(DbContext context, IMemoryCache cache, int expirtTime = 10) { CacheQueue = new ConcurrentQueue(); Context = context; Cache = cache; ExpirtTime = expirtTime; } /// /// add entity to database context and add the handle to the queue. /// ///it will be excuted when call Savechange(). ////// public void Add (TEntity entity) where TEntity : class, new() { Context.Add(entity); } /// /// add entity list to database context and add the handle to the queue. /// ///it will be excuted when call Savechange(). ////// public void AddRange (params TEntity[] entities) where TEntity : class, new() { foreach (var item in entities) Add(item); } /// /// remove entity to database context and add the handle to the queue. /// ///it will be excuted when call Savechange(). ////// public void Remove (TEntity entity) where TEntity : class, new() { bool reesult = Enqueue(entity); if (reesult) Context.Remove(entity); } /// /// remove entity list to database context and add the handle to the queue. /// ///it will be excuted when call Savechange(). ////// public void RemoveRange (params TEntity[] entities) where TEntity : class, new() { foreach (var item in entities) Remove(item); } /// /// update entity to database context and add the handle to the queue. /// ///it will be excuted when call Savechange(). ////// public void Update (TEntity entity) where TEntity : class, new() { bool reesult = Enqueue(entity); if (reesult) Context.Update(entity); } /// /// update entity list to database context and add the handle to the queue. /// ///it will be excuted when call Savechange(). ////// public void UpdateRange (params TEntity[] entities) where TEntity : class, new() { foreach (var item in entities) Update(item); } /// /// attach entity to database context add the handle to the queue. /// ///it will be excuted when call Savechange(). ////// public void Attach (TEntity entity) where TEntity : class, new() { bool reesult = Enqueue(entity); if (reesult) Context.Attach(entity); } /// /// attach entity list to database context add the handle to the queue. /// ///it will be excuted when call Savechange(). ////// public void AttachRange (params TEntity[] entities) where TEntity : class, new() { foreach (var item in entities) Attach(item); } /// /// update cache and database. /// ///update cache at first,if update cache is failed,return false,else commit the changes to database. ///public bool SaveChanges() { bool result = Dequeue(); if (result) result = Context.SaveChanges() > 0; return result; } /// /// single query. /// ///find it in the cache first,return if find it,otherwise search it in database by efcore. ////// /// public TEntity Get (string key) where TEntity : class, new() { var result = GetCache (key); if (result == null) { result = Context.Find (key); var cacheEntity = GetCacheEntity(result); AddCache(cacheEntity); } else { var cacheEntity = GetCacheEntity(result); UpdateCache(cacheEntity); } return result; } /// /// collection query. /// ///do not allow fuzzy query ////// /// public List Get (string[] keys) where TEntity : class, new() { var result = new List (); foreach (var item in keys) result.Add(Get (item)); return result; } #region private #region cache queue /// /// add the handle to the context queue. /// /// /// private bool Enqueue(object model) { CacheEntity entity = GetCacheEntity(model); if (CacheQueue.TryPeek(out CacheEntity cacheEntity1)) return false; else { CacheQueue.Enqueue(entity); return CacheQueue.TryPeek(out CacheEntity cacheEntity2); } } ////// update the changes to cache,and remove it from the cache queue. /// ///include add,delete and update. ///private bool Dequeue() { bool check = false; bool dequeue = CacheQueue.TryDequeue(out CacheEntity cacheEntity); if (dequeue) check = RemoveCache(cacheEntity); else check = false; return check; } #endregion #region cache core /// /// add cache /// /// ///private bool AddCache(CacheEntity cacheEntity) { bool check; Cache.Set(cacheEntity.key, cacheEntity.Value, new TimeSpan(0, 0, ExpirtTime)); check = Cache.Get(cacheEntity.key) != null; return check; } /// /// remove cache. /// /// ///private bool RemoveCache(CacheEntity cacheEntity) { bool check; Cache.Remove(cacheEntity.key); check = Cache.Get(cacheEntity.key) == null; return check; } /// /// update cache. /// /// ///private bool UpdateCache(CacheEntity cacheEntity) { bool check = RemoveCache(cacheEntity); if (check) check = AddCache(cacheEntity); return check; } /// /// get cache by key. /// ////// private TEntity GetCache (string key) where TEntity : class, new() { Cache.TryGetValue(key, out object value); return value as TEntity; } #endregion #region other /// /// get private cache entity. /// /// /// ///private CacheEntity GetCacheEntity(object model) { var key = GetModelKey(model); var entity = new CacheEntity() { Value = model, key = key }; return entity; } /// /// get the key of a entity. /// /// ///private string GetModelKey(object model) { string key = ""; var type = model.GetType().GetProperties(); foreach (var item in type) { if (item.GetCustomAttributes(typeof(KeyAttribute), true).Length > 0) { key = item.GetValue(model).ToString(); break; } } return key; } #endregion #endregion } /// /// a entity to handle cache /// public sealed class CacheEntity { ////// cache key /// [Key] public string key { get; set; } ////// cache value /// public object Value { get; set; } }}