C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现之方法二:加入缓存机制
在上一篇文章中我用递归方法实现了管理菜单,在上一节我也提到要考虑用缓存,也算是学习一下.Net Core的缓存机制。
关于.Net Core的缓存,官方有三种实现:
1.In Memory Caching 我理解是在内容中实现,这种方法适用于单服务器的生产环境。
2.a Distributed Cache 分部式缓存实现。
3.Response Cache 这种方式我理解为客户端缓存。
今天我只用了第一种实现方法,内存中缓存,之所以用这种方法我是觉得我这里用缓存的初衷是为了减少访问数据库的次数,而把访问数据库频率最高的数据转变为对象而放在缓存里。对于分部式说实话目前我也只是听说和了解原理,而没有做过实现,这里先不谈它。
微软官方提供的实现In Memory Caching 方法时有一个微软标准的示例,GitHub地址是 在这里
示例是用中间件实现的,经过一番学习,用示例里面提到的方法通过中间件实现了缓存,但怎么用到Controller里成了一个难题,也可能是我对中间件的了解不够深入吧!反正我是不知道该怎么办了!无耐之下,还是仔细研究了一下代码发现在中间件里面对缓存的调用(包括设置和取出)其实只在下面这段代码里实现:
if(!_memoryCache.TryGetValue(cacheKey, out greeting))
{
// fetch the value from the source
greeting = _greetingService.Greet("world"); // store in the cache
_memoryCache.Set(cacheKey, greeting,
new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromMinutes()));
_logger.LogInformation($"{cacheKey} updated from source.");
}
else
{
_logger.LogInformation($"{cacheKey} retrieved from cache.");
}
也就是 _memoryCache.TryGetValue(cacheKey, out greeting)这一段负责从缓存中取出缓存内容;而_memoryCache.Set(cacheKey, greeting, new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromMinutes(1)));这个方法调用是把数据放到缓存里面的!
知道了这些以后就着手改造我的程序了:
1.创建IAdminTreeService.cs接口类:
public interface IAdminTreeService
{
/// <summary>
/// 全部节点数据树
/// </summary>
AdminUserTree GetAllTreeData { get; }
}
2.创建服务AdminTreeServices.cs,用于实现从数据库中取出管理菜单数据,用服务方式实现这种方式还是借鉴了官方示例的实现方式,这种实现是有其道理的。道理自己琢磨吧,最起码有得用接口统一。不再啰嗦直接代码:
public class AdminTreeServices:IAdminTreeService
{
/// <summary>
/// EF数据访问配置
/// </summary>
private readonly ApplicationDbContext _basecontext; public AdminTreeServices(ApplicationDbContext context)
{
_basecontext = context;
} /// <summary>
/// 建立无限极节点树-管理菜单
/// </summary>
/// <returns></returns>
public AdminUserTree GetAllTreeData
{
get
{
AdminUserTree result = new AdminUserTree();
//初始化一个节点做为根节点
result.NodeID = ;
result.Text = "管理员菜单";
result.Url = "";
result.ParentID = -;
result.Location = "";
result.OrderID = ;
result.Comment = "来源为数据库";
result.ImageUrl = "";
result.PermissionID = ;
result.Level = ;
result.ChildNumberl = ;
//把根节点传递给递归方法去创建子节点
result.ChildNode = BuildMenuTree(result, -);
return result; } } /// <summary>
/// 递归创建子节点方法
/// </summary>
/// <param name="node">要为其分配子节点的父级节点</param>
/// <param name="levelID">层级关系</param>
/// <returns></returns>
protected List<AdminUserTree> BuildMenuTree(AdminUserTree node, int levelID)
{
var listtree = _basecontext.Admintree; //从数据库中取出node节点的全部子节点 条件:m.ParentID==node.NodeID
List<AdminUserTree> lt = listtree.Where(m => m.ParentID == node.NodeID)
.Select(m => new AdminUserTree()
{
NodeID = m.NodeID
,
Text = m.Text
,
Url = m.Url
,
ParentID = m.ParentID
,
Location = m.Location
,
OrderID = m.OrderID
,
Comment = m.Comment
,
ImageUrl = m.ImageUrl
,
PermissionID = m.PermissionID
})
.ToList(); if (lt != null)
{
//节点深度
node.Level = levelID + ;
//子节点数量,便于前端递归输出时调用
node.ChildNumberl = lt.Count;
for (int i = ; i < lt.Count; i++)
{
//递归调用创建子节点
lt[i].ChildNode = BuildMenuTree(lt[i], node.Level);
}
return lt; }
else
{
return null;
} } }
AdminTreeServices
3.管理页面基类 AdminBase.cs:
public class AdminBase: Controller
{
/// <summary>
/// EF数据访问配置
/// </summary>
private readonly ApplicationDbContext _basecontext;
private readonly IAdminTreeService _adminTreeService;
private readonly ILogger<AdminUserTree> _logger;
private readonly IMemoryCache _memoryCache; /// <summary>
/// 管理菜单 这里是基数,声明为属性以便控制器里面可以用到
/// </summary>
public AdminUserTree leftMenu { get; set; } public AdminBase(ApplicationDbContext context,
IMemoryCache memoryCache,
ILogger<AdminUserTree> logger,
IAdminTreeService adminTreeService)
{
_basecontext = context;
//初始化无限极分类管理菜单
_logger = logger;
_adminTreeService = adminTreeService;
_memoryCache = memoryCache;
leftMenu = GetAdminTreeByCache();
} /// <summary>
/// 从缓存中读取节点树
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public AdminUserTree GetAdminTreeByCache()
{
string cacheKey = "AdminTree-Base";
AdminUserTree adminTree; //获取缓存内容的一种方式
// greeting = _memoryCache.Get(cacheKey) as string; //另一种获取缓存内容的方式,
// alternately, TryGet returns true if the cache entry was found
if (!_memoryCache.TryGetValue(cacheKey, out adminTree))
{
//缓存中不存在该内容,从数据接口中通过访问数据库获取。
adminTree = _adminTreeService.GetAllTreeData; // 绝对过期时间方法,在设置缓存时3分钟后过期
//_memoryCache.Set(cacheKey, adminTree,
// new MemoryCacheEntryOptions()
// .SetAbsoluteExpiration(TimeSpan.FromMinutes(3)));
//相对过期时间方法,相对于最后一次调用后3分钟过期
_memoryCache.Set(cacheKey, adminTree,
new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromMinutes()));
//记录日志
_logger.LogInformation($"{cacheKey} From Data."+DateTime.Now.AddMinutes().ToString());
}
else
{
//记录日志,这里表示当前数据是从缓存中读取的。
_logger.LogInformation($"{cacheKey} From Cacha."+DateTime.Now.ToString());
} return adminTree; }
}
AdminBase
4.最后不要忘记了在Startup.cs中加入以下代码 :
public void ConfigureServices(IServiceCollection services)
{
…………
services.AddMemoryCache(); services.AddTransient<IAdminTreeService, AdminTreeServices>();
}
在这里基本就实现了通过缓存读取数据了!至于Controller中的实现没有变化请参考我的上篇随笔:
C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现
为了方便阅读这里再放一遍菜单节点类代码:
/// <summary>
/// 无限极节点类
/// </summary>
public class AdminUserTree
{
/// <summary>
/// 节点信息
/// </summary>
public int NodeID { get; set; }
/// <summary>
/// 节点名称
/// </summary>
public string Text { get; set; }
/// <summary>
/// 父节点ID
/// </summary>
public int ParentID { get; set; }
/// <summary>
/// 对应的链接地址
/// </summary>
public string Url { get; set; }
public int? PermissionID { get; set; }
public int? OrderID { get; set; }
public string Location { get; set; }
public string Comment { get; set; }
public string ImageUrl { get; set; }
/// <summary>
/// 层级
/// </summary>
public int Level { get; set; }
/// <summary>
/// 子节点数目(很重要)
/// </summary>
public int ChildNumberl { get; set; } /// <summary>
/// 子节点 (子节点是一个List)这种用法叫什么?
/// </summary>
public List<AdminUserTree> ChildNode { get; set; }
}
最后把运行时日志截图放出来:
首次访问:

上面有很多的数据库访问语句,日志提示数据来源与数据库
再次访问:

这里就是直接从缓存中读取出来的内容了!
好了今天的内容就写到这里。
按照先前的计划,下一步该研究一下用户及权限的内容了,这次我打算研究一下 ASP.NET Identity 身份验证和基于角色的授权,网上有很多相关的资料了,可我还是没有看明白怎么和我实际的项目相结合。估计要花几天时间了!
C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现之方法二:加入缓存机制的更多相关文章
- C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现
今天做一个管理后台菜单,想着要用无限极分类,记得园子里还是什么地方见过这种写法,可今天找了半天也没找到,没办法静下心来自己写了: 首先创建节点类(我给它取名:AdminUserTree): /// & ...
- sqlalchemy tree 树形分类 无限极分类的管理。预排序树,左右值树。sqlalchemy-mptt
简介: 无限极分类是一种比较常见的数据格式,生成组织结构,生成商品分类信息,权限管理当中的细节权限设置,都离不开无限极分类的管理. 常见的有链表式,即有一个Pid指向上级的ID,以此来设置结构.写的时 ...
- 无限极分类php实现—查子孙树、家谱树
1.本文更新日期:2018/05/20 , 亲测可用,在原有基础上进行增强和 详细化 . 2.面包屑导航 和 子孙树 效果图如下: 3.代码: <?php // 无限级分类中,查家谱树(面包屑导 ...
- js实现无限极分类
转载注明出处!!! 转载注明出处!!! 转载注明出处!!! 因为要实现部门通讯录,后台传来的数据是直接从数据库里拿的部门表,所以没有层级分类,只有parentId表示从属关系,所以分类的事情就交给我来 ...
- 夺命雷公狗ThinkPHP项目之----企业网站8之栏目的添加完善(无限极分类的完成)
我们刚才只是完成了添加的一部分,但是我们的上级分类也不能永远都是只有一个死的嘛,所以我们需要对她进行修改: 我们先将add方法里面的数据查出来再说: 然后在模板页进行遍历: 展示效果如下所示: 虽然是 ...
- DotNet菜鸟入门之无限极分类(一)设计篇
写这个教程的原因,是因为,无限极分类,在许多项目中,都用得到.而对于新手来说,不是很好理解,同时,操作上也有一些误区或者不当之处.所以我就斗胆,抛砖引玉一下,已一个常见的后台左侧频道树为例子,讲解一下 ...
- PHP实现菜单无限极分类
菜单数据 这里我们的菜单数据是临时数据, 没有从数据库中查询处理,数据基本和数据库中的的相似. 数据如下: $items = array( 1 => array('id' => 1, 'p ...
- php无限极分类以及递归(thinkphp)
php无限极分类: 无限极分类重点在于表的设计: 1在model中: class CatModel extends Model{ protected $cat = array(); public fu ...
- PHP无限极分类,多种方法|很简单,这里说的很详细,其它地方说的很不好懂
当你学习php无限极分类的时候,大家都觉得一个字"难"我也觉得很难,所以,现在都还在看,因为工作要用到,所以,就必须得研究研究. 到网上一搜php无限极分类,很多,但好多都是一 ...
随机推荐
- Union-Find 检测无向图有无环路算法
不相交集合数据结构(Disjoint-set data structure)是一种用于跟踪集合被分割成多个不相交的子集合的数据结构,每个集合通过一个代表来标识,代表即集合中的某个成员. Union-F ...
- Hadoop学习笔记—17.Hive框架学习
一.Hive:一个牛逼的数据仓库 1.1 神马是Hive? Hive 是建立在 Hadoop 基础上的数据仓库基础构架.它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储. ...
- Intro to CSS 3D transforms
原文地址:Intro to CSS 3D transforms,本文只是翻译了其中的一部分,省去了作者写文章的原因浏览器兼容部分(已经过时) Perspective 元素需要设置需要设置perspec ...
- Tomcat 让百度的域名显示自己的页面内容(玩耍篇)
步骤一:在 C:\Windows\System32\drivers\etc目录下的Hosts文件中添多一个条目,如下图, 第二步:在server.xml文件中做响应配置,如下图 然后在Host节点中进 ...
- 【VC++技术杂谈005】如何与程控仪器通过GPIB接口进行通信
在工控测试系统中,经常需要使用到各类程控仪器,这些程控仪器通常具有GPIB.LAN.USB等硬件接口,计算机通过这些接口能够与其通信,从而实现自动测量.数据采集.数据分析和数据处理等操作.本文主要介绍 ...
- 在JS中获取文件点之后的后缀字符
var upFileName = $("#fileToUpload").val();var index1=upFileName.lastIndexOf(".") ...
- AngularJs入门之表单开发
本文和大家分享的主要是前端开发中必备的AngularJs框架表单开发相关基础知识,希望对大家使用和学习AngularJs有所帮助. 1.简单的表单提交: 2.更多的表单元素: 3.初始化表单: 代码 ...
- Sublime 快捷键
语法快捷键: 后代:> 缩写:nav>ul>li <nav> <ul> <li></li> </ul> </nav& ...
- 使用Ado.net执行SP很慢,而用SSMS执行很快
今天遇到一个问题,有用户反应,在site上打开报表,一直loading,出不来结果. 遇到这种问题,我立刻simulate用户使用Filter Condition,问题repro,看来不是偶然事件,通 ...
- 免费获取WP之类的开发者权限或免费使用Azure 2015-10-19
上一次弄wp真机调试的时候,卡住了,这里讲一下怎么解决(http://www.cnblogs.com/dunitian/p/4870959.html) 进这个网址注册一下:https://www.dr ...