.NetCore 内置缓存加入到EFCore操作中,数据更新或者查询时自动更新缓存。github地址

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
{
/// <summary>
/// a queue to save the handle,if will be empted when call savechanges().
/// </summary>
private ConcurrentQueue<CacheEntity> CacheQueue { get; set; } /// <summary>
/// databse context.
/// </summary>
private DbContext Context { get; set; } /// <summary>
/// netocre inner cache.
/// </summary>
private IMemoryCache Cache { get; set; } /// <summary>
/// the time of cache's life cycle
/// </summary>
private int ExpirtTime { get; set; } = 10; /// <summary>
/// entity context.
/// </summary>
/// <param name="context">database context</param>
/// <param name="cache">cache</param>
/// <param name="expirtTime">expirt time,default 60 sencond.</param>
public DefaultContext(DbContext context, IMemoryCache cache, int expirtTime = 10)
{
CacheQueue = new ConcurrentQueue<CacheEntity>();
Context = context;
Cache = cache;
ExpirtTime = expirtTime;
} /// <summary>
/// add entity to database context and add the handle to the queue.
/// <para>it will be excuted when call Savechange().</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entity"></param>
public void Add<TEntity>(TEntity entity)
where TEntity : class, new()
{
Context.Add(entity);
} /// <summary>
/// add entity list to database context and add the handle to the queue.
/// <para>it will be excuted when call Savechange().</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entities"></param>
public void AddRange<TEntity>(params TEntity[] entities)
where TEntity : class, new()
{
foreach (var item in entities)
Add(item);
} /// <summary>
/// remove entity to database context and add the handle to the queue.
/// <para>it will be excuted when call Savechange().</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entity"></param>
public void Remove<TEntity>(TEntity entity)
where TEntity : class, new()
{
bool reesult = Enqueue(entity);
if (reesult)
Context.Remove(entity);
} /// <summary>
/// remove entity list to database context and add the handle to the queue.
/// <para>it will be excuted when call Savechange().</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entities"></param>
public void RemoveRange<TEntity>(params TEntity[] entities)
where TEntity : class, new()
{
foreach (var item in entities)
Remove(item);
} /// <summary>
/// update entity to database context and add the handle to the queue.
/// <para>it will be excuted when call Savechange().</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entity"></param>
public void Update<TEntity>(TEntity entity)
where TEntity : class, new()
{
bool reesult = Enqueue(entity);
if (reesult)
Context.Update(entity);
} /// <summary>
/// update entity list to database context and add the handle to the queue.
/// <para>it will be excuted when call Savechange().</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entities"></param>
public void UpdateRange<TEntity>(params TEntity[] entities)
where TEntity : class, new()
{
foreach (var item in entities)
Update(item);
} /// <summary>
/// attach entity to database context add the handle to the queue.
/// <para>it will be excuted when call Savechange().</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entities"></param>
public void Attach<TEntity>(TEntity entity)
where TEntity : class, new()
{
bool reesult = Enqueue(entity);
if (reesult)
Context.Attach(entity);
} /// <summary>
/// attach entity list to database context add the handle to the queue.
/// <para>it will be excuted when call Savechange().</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entities"></param>
public void AttachRange<TEntity>(params TEntity[] entities)
where TEntity : class, new()
{
foreach (var item in entities)
Attach(item);
} /// <summary>
/// update cache and database.
/// <para>update cache at first,if update cache is failed,return false,else commit the changes to database.</para>
/// </summary>
/// <returns></returns>
public bool SaveChanges()
{
bool result = Dequeue();
if (result)
result = Context.SaveChanges() > 0;
return result;
} /// <summary>
/// single query.
/// <para>find it in the cache first,return if find it,otherwise search it in database by efcore.</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public TEntity Get<TEntity>(string key)
where TEntity : class, new()
{
var result = GetCache<TEntity>(key);
if (result == null)
{
result = Context.Find<TEntity>(key);
var cacheEntity = GetCacheEntity(result);
AddCache(cacheEntity);
}
else
{
var cacheEntity = GetCacheEntity(result);
UpdateCache(cacheEntity);
}
return result;
} /// <summary>
/// collection query.
/// <para>do not allow fuzzy query</para>
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="keys"></param>
/// <returns></returns>
public List<TEntity> Get<TEntity>(string[] keys)
where TEntity : class, new()
{
var result = new List<TEntity>();
foreach (var item in keys)
result.Add(Get<TEntity>(item));
return result;
} #region private #region cache queue /// <summary>
/// add the handle to the context queue.
/// </summary>
/// <param name="model"></param>
/// <param name="handleEnum"></param>
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);
}
} /// <summary>
/// update the changes to cache,and remove it from the cache queue.
/// <para>include add,delete and update.</para>
/// </summary>
/// <returns></returns>
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 /// <summary>
/// add cache
/// </summary>
/// <param name="cacheEntity"></param>
/// <returns></returns>
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;
} /// <summary>
/// remove cache.
/// </summary>
/// <param name="cacheEntity"></param>
/// <returns></returns>
private bool RemoveCache(CacheEntity cacheEntity)
{
bool check;
Cache.Remove(cacheEntity.key);
check = Cache.Get(cacheEntity.key) == null;
return check;
} /// <summary>
/// update cache.
/// </summary>
/// <param name="cacheEntity"></param>
/// <returns></returns>
private bool UpdateCache(CacheEntity cacheEntity)
{
bool check = RemoveCache(cacheEntity);
if (check)
check = AddCache(cacheEntity);
return check;
} /// <summary>
/// get cache by key.
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
private TEntity GetCache<TEntity>(string key)
where TEntity : class, new()
{
Cache.TryGetValue(key, out object value);
return value as TEntity;
} #endregion #region other /// <summary>
/// get private cache entity.
/// </summary>
/// <param name="model"></param>
/// <param name="handleEnum"></param>
/// <returns></returns>
private CacheEntity GetCacheEntity(object model)
{
var key = GetModelKey(model);
var entity = new CacheEntity()
{
Value = model,
key = key
};
return entity;
} /// <summary>
/// get the key of a entity.
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
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
} /// <summary>
/// a entity to handle cache
/// </summary>
public sealed class CacheEntity
{
/// <summary>
/// cache key
/// </summary>
[Key]
public string key { get; set; } /// <summary>
/// cache value
/// </summary>
public object Value { get; set; }
}
}

基于EFCore的数据Cache实现的更多相关文章

  1. 基于Web的数据推送技术(转)

    基于Web的数据推送技术 对于实时性数据显示要求比较高的系统,比如竞价,股票行情,实时聊天等,我们的解决方案有以下几种.1. HTTP请求发送模式,一般可以基于ajax的请求,比如每3秒一次访问下服务 ...

  2. 【转】在Spring中基于JDBC进行数据访问时怎么控制超时

    http://www.myexception.cn/database/1651797.html 在Spring中基于JDBC进行数据访问时如何控制超时 超时分类 超时根据作用域可做如下层级划分: Tr ...

  3. 数据权限设计——基于EntityFramework的数据权限设计方案:一种设计思路

    前言:“我们有一个订单列表,希望能够根据当前登陆的不同用户看到不同类型的订单数据”.“我们希望不同的用户能看到不同时间段的扫描报表数据”.“我们系统需要不同用户查看不同的生产报表列”.诸如此类,最近经 ...

  4. 基于 PHP 的数据爬取(QueryList)

    基于PHP的数据爬取 官方网站站点 简单. 灵活.强大的PHP采集工具,让采集更简单一点. 简介: QueryList使用jQuery选择器来做采集,让你告别复杂的正则表达式:QueryList具有j ...

  5. Creating adaptive web recommendation system based on user behavior(设计基于用户行为数据的适应性网络推荐系统)

    文章介绍了一个基于用户行为数据的推荐系统的实现步骤和方法.系统的核心是专家系统,它会根据一定的策略计算所有物品的相关度,并且将相关度最高的物品序列推送给用户.计算相关度的策略分为两部分,第一部分是针对 ...

  6. 基于CentOS搭建基于 ZIPKIN 的数据追踪系统

    系统要求:CentOS 7.2 64 位操作系统 配置 Java 环境 安装 JDK Zipkin 使用 Java8 -openjdk* -y 安装完成后,查看是否安装成功: java -versio ...

  7. 基于PHP采集数据入库程序(二)

    在上篇基于PHP采集数据入库程序(一) 中提到采集新闻信息页的列表数据,接下来讲讲关于采集新闻具体内容 这是上篇博客的最终数据表截图: 接下来要做的操作就是从数据库中读取所需要采集的URL,进行页面抓 ...

  8. 基于Dedup的数据打包技术

    基于Dedup的数据打包技术 0.引言    Tar, winrar, winzip是最为常见的数据打包工具软件,它们把文件集体封装成一个单独的数据包,从而方便数据的分布.传输.归档以及持久保存等目的 ...

  9. 基于vue-easytable实现数据的增删改查

    基于vue-easytable实现数据的增删改查 原理:利用vue的数据绑定和vue-easetable的ui完成增删改查 后端接口: 1.条件查询表中数据 http://localhost:4795 ...

随机推荐

  1. WTH统计

    SELECT t2.MasterName AS '类型',SUM(t1.DailyCount) AS '数量',(CASE T2.MasterName WHEN '电子阅读' THEN '篇' WHE ...

  2. Request header field Content-Type is not allowed by Access-Control-Allow-Headers

    今天遇到一个跨域问题记录学习下: 一.问题: 跨域请求中包含自定义header字段时,浏览器console报错. Request header field xfilesize is not allow ...

  3. 数据存储-- Core Data的使用(二)

    一.基础概念深入 1.NSManagedObjectContext 被管理数据上下文就像便笺簿 当从数据持久层获取数据时,相当于把这些临时的数据拷贝写在便笺簿上,然后就可以随心所欲的修改这些值. 通过 ...

  4. git checkout 报错 refname 'origin/branch-name' is ambiguous

    When this happened, it created the file .git/refs/heads/origin/branch-name. So, I just deleted the f ...

  5. widow系统 LuaForWindows,安装 luasocket

    参考 http://94it.net/a/jingxuanboke/2013/0625/49052.html 1. 我用的是 LuaForWindows_v5.1.4-46.exe 可以在我的百度网盘 ...

  6. Vim技能修炼教程(6) - 行编辑器

    在很久很久以前,计算机的运算能力还很弱,终端与主机的通信也不好.在没有显示器的时代,只能通过电传打字机跟主机通信.那时候只有行编辑器,编辑的时候只能在一行中进行.需要显示哪一行,就把哪一行或者哪几行打 ...

  7. 【干货】Kaggle 数据挖掘比赛经验分享(mark 专业的数据建模过程)

    简介 Kaggle 于 2010 年创立,专注数据科学,机器学习竞赛的举办,是全球最大的数据科学社区和数据竞赛平台.笔者从 2013 年开始,陆续参加了多场 Kaggle上面举办的比赛,相继获得了 C ...

  8. 【Hibernate实战】源码解析Hibernate参数绑定及PreparedStatement防SQL注入原理

        本文采用mysql驱动是5.1.38版本. 本篇文章涉及内容比较多,单就Hibernate来讲就很大,再加上数据库驱动和数据库相关,非一篇文章或一篇专题就能说得完.本文从使用入手在[Spr ...

  9. tensorflow图像基本处理

    tensorflow库提供的专门的图片处理库,以下只是部分示例,更多函数请参照源码'\tensorflow_api\v1\image__init__.py' 加载图像 方式1: 使用tf.gfile. ...

  10. BZOJ3963: [WF2011]MachineWorks 【CDQ+斜率优化DP】*

    BZOJ3963: [WF2011]MachineWorks Description 你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM)的经理,公司使用更加先 ...