基于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 ...
随机推荐
- Django 中设置分页页码,只显示当前页以及左右两页
设置后的效果如下: Django 给我们提供了分页的功能:`Paginator`和`Page`类都是用来做分页的.他们在Django中的路径为:`from django.core.paginator ...
- 001——vue.js初始安装:
windows下安装: 1.https://nodejs.org/en/ 下载安装node.js. 在cmd窗口输入node -v检查node是否安装成功. npm也随着node安装了:npm -v ...
- node.js利用express连接mysql数据库
我们创建一个mysql.js (好像大神们,称呼这叫一个模块,然后暴露一个接口)用来连接数据库 var connction ={}; connction.mysql = { host:"lo ...
- NPOI 生成 Excel
前言 在 c# 中可以使用对应的com组件生成或操作excel,但前提是必须安装了Office Excel , 但服务器端不一定会安装Excel,而且它操作起来并不简单.但是,使用NPOI这个第三 ...
- linux中安装eclipse--CnetOS6.5
01.去官网下载指定的eclipse安装包 02.使用xftp把下载的eclipse安装包放入到linux系统的指定位置03.到指定的目录下!使用命令解压下载的文件tar -zxvf 文件名称04. ...
- LeetCode OJ:Isomorphic Strings(同构字符串)
Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the chara ...
- Spring容器三种注入类型
Spring注入有三种方式: 1.Set注入(使用最多) 2.构造器注入(使用不多) 3.接口注入(几乎不用)不做测试了 1.Set注入:所谓Set注入就是容器内部调用了bean的Set***方法,注 ...
- C与C++基础知识补遗
本随笔用来记载项目开发中遇到的以前没掌握的C/C++基础知识 void * buffer; 无类型指针,可以指向任何类型数据.ANSI标准规定无类型指针不能进行算法,而GNU规定无类型指针算法操作与c ...
- Linux:uniq命令详解
uniq uniq命令用于报告或忽略文件中的重复行,一般与sort命令结合使用. 语法 uniq(选项)(参数) 选项 -c或——count:在每列旁边显示该行重复出现的次数: -d或--repeat ...
- jsp采用数据库连接池的方法获取数据库时间戳context.xml配置,jsp页面把时间格式化成自己需要的格式
<?xml version="1.0" encoding="UTF-8"?> <!-- 数据库连接池配置文件 --> <Conte ...