基于EFCore的数据Cache实现
.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实现的更多相关文章
- 基于Web的数据推送技术(转)
基于Web的数据推送技术 对于实时性数据显示要求比较高的系统,比如竞价,股票行情,实时聊天等,我们的解决方案有以下几种.1. HTTP请求发送模式,一般可以基于ajax的请求,比如每3秒一次访问下服务 ...
- 【转】在Spring中基于JDBC进行数据访问时怎么控制超时
http://www.myexception.cn/database/1651797.html 在Spring中基于JDBC进行数据访问时如何控制超时 超时分类 超时根据作用域可做如下层级划分: Tr ...
- 数据权限设计——基于EntityFramework的数据权限设计方案:一种设计思路
前言:“我们有一个订单列表,希望能够根据当前登陆的不同用户看到不同类型的订单数据”.“我们希望不同的用户能看到不同时间段的扫描报表数据”.“我们系统需要不同用户查看不同的生产报表列”.诸如此类,最近经 ...
- 基于 PHP 的数据爬取(QueryList)
基于PHP的数据爬取 官方网站站点 简单. 灵活.强大的PHP采集工具,让采集更简单一点. 简介: QueryList使用jQuery选择器来做采集,让你告别复杂的正则表达式:QueryList具有j ...
- Creating adaptive web recommendation system based on user behavior(设计基于用户行为数据的适应性网络推荐系统)
文章介绍了一个基于用户行为数据的推荐系统的实现步骤和方法.系统的核心是专家系统,它会根据一定的策略计算所有物品的相关度,并且将相关度最高的物品序列推送给用户.计算相关度的策略分为两部分,第一部分是针对 ...
- 基于CentOS搭建基于 ZIPKIN 的数据追踪系统
系统要求:CentOS 7.2 64 位操作系统 配置 Java 环境 安装 JDK Zipkin 使用 Java8 -openjdk* -y 安装完成后,查看是否安装成功: java -versio ...
- 基于PHP采集数据入库程序(二)
在上篇基于PHP采集数据入库程序(一) 中提到采集新闻信息页的列表数据,接下来讲讲关于采集新闻具体内容 这是上篇博客的最终数据表截图: 接下来要做的操作就是从数据库中读取所需要采集的URL,进行页面抓 ...
- 基于Dedup的数据打包技术
基于Dedup的数据打包技术 0.引言 Tar, winrar, winzip是最为常见的数据打包工具软件,它们把文件集体封装成一个单独的数据包,从而方便数据的分布.传输.归档以及持久保存等目的 ...
- 基于vue-easytable实现数据的增删改查
基于vue-easytable实现数据的增删改查 原理:利用vue的数据绑定和vue-easetable的ui完成增删改查 后端接口: 1.条件查询表中数据 http://localhost:4795 ...
随机推荐
- 弄懂flex布局
目前在不考虑IE以及低端安卓机(4.3-)的兼容下,已经可以放心使用flex进行布局了.什么是flex布局以及它的好处,这里就不再赘述. 在这篇文章里,想说说flex布局的属性语法及其细节.那么网上也 ...
- centos 7安装jenkins
1. 安装java yum install java 2. 安装jenkins wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci. ...
- 由浅入深了解EventBus:(四)
事件注册 在EventBus3.0框架中订阅者对事件进行注册/订阅是通过EventBus类中的register方法来实现的,register的方法参数就是我们的订阅者的实例; public void ...
- hdu 4770 13 杭州 现场 A - Lights Against Dudely 暴力 bfs 状态压缩DP 难度:1
Description Harry: "But Hagrid. How am I going to pay for all of this? I haven't any money.&quo ...
- 【Html 学习笔记】第四节——框架
我们经常使用的网页可能不是一个单独的网页,而是多个嵌套的,那么就需要用到下面的技术. 垂直框架:<frameset cols=""> 这里需要注意的是:四个网页需要同时 ...
- 简单的cookie盗取
此文需要有一定的javascript\html\php方面的只是作为基础 直接上代码: #用于抓取盗窃来的cookie的php文件,此文件需置于攻击者的服务器上,这里包含了两种写法:Method1和M ...
- 【跟着stackoverflow学Pandas】How to iterate over rows in a DataFrame in Pandas-DataFrame按行迭代
最近做一个系列博客,跟着stackoverflow学Pandas. 以 pandas作为关键词,在stackoverflow中进行搜索,随后安照 votes 数目进行排序: https://stack ...
- 目标检测 - Tensorflow Object Detection API
一. 找到最好的工具 "工欲善其事,必先利其器",如果你想找一个深度学习框架来解决深度学习问题,TensorFlow 就是你的不二之选,究其原因,也不必过多解释,看过其优雅的代码架 ...
- async eachSeries如何按序列执行下去
async callback要执行完才会进到一下个序列 async.mapSeries(files, function(file, outerCB) { var all = fs.readdirsyn ...
- python常用模块之shutil模块
python常用模块之shutil模块 shutil模块,高级的文件.文件夹.压缩包处理模块 1.shutil.copyfile(src,des[,length]):将文件内容拷贝到另一个文件 In ...