Asp.Net Core 缓存的使用(译)
原文:http://www.binaryintellect.net/articles/a7d9edfd-1f86-45f8-a668-64cc86d8e248.aspx
环境:Visual Studio 2017, Asp.Net Core 1.1.
缓存机制主要是为了提高性能。在ASP.NET Web Forms 及 ASP.NET MVC中可以直接使用缓存对象(Caching object)缓存数据。这通常被称作“服务器端缓存”,是 Framework 的内置特性。虽然Asp.Net Core没有这样的缓存对象,但依然可以轻松的实现缓存功能。本文将对此进行介绍。
继续阅读之前,请先使用 Web Application 项目模板创建一个 Asp.net Core 的应用程序:
注:使用缓存功能,需通过NuGet安装“Microsoft.Extensions.Caching.Memory”扩展包。使用时引用:using Microsoft.Extensions.Caching.Memory; |
1. 在Startup类中开启缓存功能
如前所述,Asp.Net Core 没有内建的缓存对象,因此不能在 Controller 中使用它们。在Asp.Net Core中要使用内存缓存,需要在 Startup 类中依赖注入(DI)内存缓存服务(in-memory caching service)。打开Startup 文件,修改 ConfigureServices() 方法如下:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddMemoryCache();
}
AddMemoryCache() 方法将内存缓存功能加入到服务集合中。
2. 控制器中注入缓存对象
修改HomeController如下:
public class HomeController : Controller
{
private IMemoryCache cache; public HomeController(IMemoryCache cache)
{
this.cache = cache;
}
...
}
通过构造函数注入缓存对象,我们在控制器中就有了可用的缓存变量。
3. 使用Set()方法缓存一个对象
有了IMemoryCache 对象,你就可以非常方便读取或写入缓存数据。
public IActionResult Index()
{
cache.Set<string>("timestamp", DateTime.Now.ToString());
return View();
}
上面代码使用 IMemoryCache 的 Set<T>() 方法将一条记录加入到了缓存中。Set() 方法第一个参数为缓存名称,第二个参数为其值。
4. 使用Get()方法获取缓存
一旦您添加了缓存,就可以通过 Get() 方法来获取它们。
public IActionResult Show()
{
string timestamp = cache.Get<string>("timestamp");
return View("Show", timestamp);
}
上面代码演示了从缓存中获得数据,Get() 方法指定了缓存名和返回数据类型。
下面用于显示获得的缓存:
<h1>TimeStamp : @Model</h1>
<h2>@Html.ActionLink("Go back", "Index", "Home")</h2>
运行你的应用程序,打开 /Home/Index ,此时将生成了一个时间戳并存入缓存中。然后打开 /Home/Show 观察是否已从缓存中获得了时间戳数据。/Home/Show 页面会显示如下:
5. 使用TryGet()方法检查是否存在指定缓存项
上面示列中,每次访问 /Home/Index 都将生成一个新的时间戳并进行缓存,这是因为没有检查是否已存在同名的缓存项。有两种方式检测同名缓存项:
//first way
if (string.IsNullOrEmpty(cache.Get<string>("timestamp")))
{
cache.Set<string>("timestamp", DateTime.Now.ToString());
} //second way
if (!cache.TryGetValue<string>("timestamp", out string timestamp))
{
cache.Set<string>("timestamp", DateTime.Now.ToString());
}
第一种方法仍然使用Get()方法,如未能获取到值,则返回 IsNullOrEmpty()。
第二种方法更加优雅一些,使用TryGet()方法获取值。TryGet()方法返回一个布尔值来表示缓存项是否存在,实际的缓存值将通过 out 参数获得。
6. 使用GetOrCreate()添加不存在的缓存项
你可能有这样的需求,缓存项如果存在则取出,如果不存在则创建。此时可以使用 GetOrCreate() 方法:
public IActionResult Show()
{
string timestamp = cache.GetOrCreate<string>("timestamp", entry => {
return DateTime.Now.ToString();
});
return View("Show", timestamp);
}
使用GetOrCreate() 方法检查timestamp是否存在,如果存在则直接赋值给本地变量,反之则创建一个新的缓存项。
现在直接访问/Home/Show页面,可以看到timestamp已显示。timestamp并没有通过/Home/Index赋值。
7. 设置缓存的决绝和滑动(sliding)期限
在之前的示列中,缓存数据会一直存在,直到调用Remove()方法。你也可以为缓存设置绝对期限和滑动期限。绝对期限就是为缓存设置一个明确的过期时间,滑动期限就是空闲多少时间之后移除缓存。
你可以通过 MemoryCacheEntryOptions对象设置缓存期限策略:
public IActionResult Index()
{
//cache.Set<string>("timestamp", DateTime.Now.ToString()); MemoryCacheEntryOptions options = new MemoryCacheEntryOptions();
options.AbsoluteExpiration = DateTime.Now.AddMinutes();
options.SlidingExpiration = TimeSpan.FromMinutes();
cache.Set<string>("timestamp", DateTime.Now.ToString(), options); return View();
}
上面代码在Index() action中创建了MemoryCacheEntryOptions对象,并同时设置了一个绝对期限为1分钟与滑动期限为1分钟的策略。MemoryCacheEntryOptions对象作为Set()方法的第三个参数传递。
8. 定义移除缓存之后的回调函数
有时候你可能需要在缓存移除后获得通知。缓存被移除有以下2种原因,一是调用了Remove()方法,二是到期后自动移除。你可以通过设定回调函数获得移除缓存之后的通知:
public IActionResult Index()
{
//cache.Set<string>("timestamp", DateTime.Now.ToString()); MemoryCacheEntryOptions options = new MemoryCacheEntryOptions();
options.AbsoluteExpiration = DateTime.Now.AddMinutes();
options.SlidingExpiration = TimeSpan.FromMinutes();
options.RegisterPostEvictionCallback(MyCallback, this);
cache.Set<string>("timestamp", DateTime.Now.ToString(), options); return View();
}
上面代码示例了通过RegisterPostEvictionCallback方法设定回调函数,在本例中回调函数名为MyCallback,第二个参数是你希望传递给回调函数的状态参数,本例我们将HomeController实例作为状态参数传递给回调函数。
回调函数方法如下:
private static void MyCallback(object key, object value, EvictionReason reason, object state)
{
var message = $"Cache entry was removed : {reason}";
((HomeController)state).cache.Set("callbackMessage", message);
}
看看上面代码,MyCallback() 是一个在HomeController中的私有静态函数,有四个参数。前两个参数是被移除的缓存数据所对应的键/值,第三个参数表示移除的原因。EvictionReason是一个枚举类型,可能原因有过期、移除和替换。
在函数体中,我们仅定义了一个string类型的message表示移除原因。如果我们想要把这个message作为另一个缓存项,就需要访问HomeController的缓存对象,此时就要使用第四个参数state。使用state对象获得HomeController中的缓存,同时使用Set()方法设置了一个名为“callbackMessage”的缓存项。
callbackMessage可以在Show() action中获得:
public IActionResult Show()
{
string timestamp = cache.Get<string>("timestamp");
ViewData["callbackMessage"] = cache.Get<string>("callbackMessage");
return View("Show", timestamp);
}
在Show页面呈现:
<h1>TimeStamp : @Model</h1>
<h3>@ViewData["callbackMessage"]</h3>
<h2>@Html.ActionLink("Go back", "Index", "Home")</h2>
测试回调方法,运行程序并访问/Home/Index页面,然后再访问/Home/Show页面,不断刷新Show页面直到缓存过期,页面会显示过期原因。
9. 缓存的优先级
和过期策略一样,缓存优先级同样使用MemoryCacheEntryOptions:
MemoryCacheEntryOptions options = new MemoryCacheEntryOptions();
options.Priority = CacheItemPriority.Normal;
cache.Set<string>("timestamp", DateTime.Now.ToString(), options);
CacheItemPriority枚举值有普通,高和永久保留。
10. 设置缓存之间的依赖关系
可以为缓存数据设置依赖关系,实现删除一个缓存项后,其依赖的缓存项同时被移除的功能。请按如下代码更新Index() action:
public IActionResult Index()
{
var cts = new CancellationTokenSource();
cache.Set("cts", cts); MemoryCacheEntryOptions options = new MemoryCacheEntryOptions();
options.AddExpirationToken(new CancellationChangeToken(cts.Token));
options.RegisterPostEvictionCallback(MyCallback, this);
cache.Set<string>("timestamp",DateTime.Now.ToString(), options); cache.Set<string>("key1", "Hello World!",new CancellationChangeToken(cts.Token));
cache.Set<string>("key2", "Hello Universe!",new CancellationChangeToken(cts.Token)); return View();
}
注:通过NuGet安装“Microsoft.Extensions.Primitives”程序包,同时添加对System.Threading的引用。 |
上面代码首先创建了一个CancellationTokenSource对象,并将其设置成名为“cts”的缓存项。然后创建MemoryCacheEntryOptions对象,并使用AddExpirationToken()方法指定一个特殊的过期令牌(expiration token),这里我们暂不深究CancellationChangeToken。
expiration token允许你“过期”一个缓存项,如果令牌是“active”状态则保留缓存项,如果是“cancelled”则从缓存中移除。一旦缓存项被移除则调用MyCallback方法。代码接着创建了两个缓存项 key1和key2,创建时第三参数传递了一个使用cts对象初始化的CancellationChangeToken。
现在我们有了三个缓存项,timestamp是主缓存项,key1和key2依赖与timestamp。当timestamp被移除时,会同时移除key1和key2。移除timestamp需要取消它的令牌。
public IActionResult Remove()
{
CancellationTokenSource cts = cache.Get<CancellationTokenSource>("cts");
cts.Cancel();
return RedirectToAction("Show");
}
我们从缓存中获得先前定义的CancellationTokenSource对象同时执行Cancel()方法,timestamp移除的同时key1与key2也一并移除了。
测试一下上面代码,运行程序并访问/Home/Index页面,再访问/Home/Show页面,同时检查三个缓存项是否按预期显示。然后访问/Home/Remove,你将重新被导航到/Home/Show页面。当Remove() action被调用时,令牌被标记为取消,所有的值将被移除。Show页面将显示过期原因为“令牌过期”:
Asp.Net Core 缓存的使用(译)的更多相关文章
- ASP.NET Core 缓存技术 及 Nginx 缓存配置
前言 在Asp.Net Core Nginx部署一文中,主要是讲述的如何利用Nginx来实现应用程序的部署,使用Nginx来部署主要有两大好处,第一是利用Nginx的负载均衡功能,第二是使用Nginx ...
- Asp.net Core 缓存 MemoryCache 和 Redis
Asp.net Core 缓存 MemoryCache 和 Redis 目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 经过 N 久反复的尝试,翻阅了网上无数的资料,GitH ...
- Redis 入门与 ASP.NET Core 缓存
目录 基础 Redis 库 连接 Redis 能用 redis 干啥 Redis 数据库存储 字符串 订阅发布 RedisValue ASP.NET Core 缓存与分布式缓存 内存中的缓存 ASP. ...
- 【无私分享:ASP.NET CORE 项目实战(第十一章)】Asp.net Core 缓存 MemoryCache 和 Redis
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 经过 N 久反复的尝试,翻阅了网上无数的资料,GitHub上下载了十几个源码参考, Memory 和 Redis 终于写出一个 ...
- ASP.NET Core缓存静态资源
背景 缓存样式表,JavaScript或图像文件等静态资源可以提高您网站的性能.在客户端,总是从缓存中加载一个静态文件,这样可以减少对服务器的请求数量,从而减少获取页面及其资源的时间.在服务器端,由于 ...
- asp.net core 缓存和Session
缓存 缓存在内存中 ASP.NET Core 使用 IMemoryCache内存中缓存是使用依赖关系注入从应用中引用的服务. 请在ConfigureServices中调用AddMemoryCache( ...
- ASP.NET Core 中间件之压缩、缓存
前言 今天给大家介绍一下在 ASP.NET Core 日常开发中用的比较多的两个中间件,它们都是出自于微软的 ASP.NET 团队,他们分别是 Microsoft.AspNetCore.Respons ...
- ASP.NET Core 开发-缓存(Caching)
ASP.NET Core 缓存Caching,.NET Core 中为我们提供了Caching 的组件. 目前Caching 组件提供了三种存储方式. Memory Redis SqlServer 学 ...
- [译]ASP.NET Core 2.0 系列文章目录
基础篇 [译]ASP.NET Core 2.0 中间件 [译]ASP.NET Core 2.0 带初始参数的中间件 [译]ASP.NET Core 2.0 依赖注入 [译]ASP.NET Core 2 ...
随机推荐
- #error#学习方法,如何避免初始化错误
#error#学习方法,如何避免初始化错误.错误来自:本博客的另一篇文章Demo示例程序源代码: ,01-导航实例-QQ空间.xcodeproj - CYLLoginViewController.mD ...
- ubuntu16.04搭建个人简易DLP
前言 最近一朋友让我帮忙搭建一台服务器,用做公司的服务器,但是该服务器需要满足一些安全要求,于是乎就有了下面的解决过程^_^ 需求 期望普通用户和管理员都能ssh登陆服务器,但禁止scp或者其他方式下 ...
- ZOJ 3598 Spherical Triangle球面几何公式应用
#include <map> #include <set> #include <list> #include <cmath> #include < ...
- PHPExcel 使用(1)
最近在项目中要用到PHP生成EXCEL,上网找了一下,发现PHPEXCEL挺不错,用了一下,感觉还行,就是设置单元格格式的时候比较麻烦,总体来说功能还是比较强大的,还有生成PDF什么的,发一个实例吧 ...
- 【SQL】使用调用层接口
只记录C语言相关的,java相关的JDBC和PHP相关的都先跳过. C相关的也只是记录一下,这里面的语句我都不知道如何运行,在我的vs2010里面连头文件都找不到... 我觉得这里只是讲解了一下基本的 ...
- 【C++】嵌套类、友元
黄邦勇帅 里面关于嵌套类的介绍我有疑惑.里面11.9说在创建一个外围类的对象时先执行嵌套类的构造函数然后再执行外围类的构造函数,析构函数则以相反的方式执行. 可是我编程实验了一下,创建外围类对象时并不 ...
- [设计模式-行为型]观察者模式(Observer)
一句话 事件监听就是观察者模式最好的例子. 概括
- k8s的chart学习(上)
chart 是 Helm 的应用打包格式.chart 由一系列文件组成,这些文件描述了 Kubernetes 部署应用时所需要的资源,比如 Service.Deployment.PersistentV ...
- ionic 之环境的搭建
在ionic的学习中,首先要做的就是环境的搭建,接下来我对从一开始环境的搭建做了记录,以及过程中遇到的问题. 1.安装环境 1.1 安装Node.js Node.js建议安装最新版本,下载地址:htt ...
- python操作数据库的几种方式
参照python 操作mysql python-mysqldb : http://www.cnblogs.com/wupeiqi/articles/5095821.html (python3 不支持) ...