关于 ASP.NET 内存缓存你需要知道的 10 点

缓存机制的主要目的是提高应用程序的性能。作为 ASP.NET 开发人员,你可能会意识到 ASP.NET Web 窗体以及 ASP.NET MVC 可以使用 Cache 对象缓存应用程序的数据。这通常被称为服务器端数据缓存,并且常作为框架的内置功能。虽然 ASP.NET Core 中并没有这样的 Cache 对象,但是你可以很容易地实现内存缓存。本文将向你说明如何实现。

在进一步阅读之前,你先创建一个基于 Web 应用程序项目模板的新的 ASP.NET Core 应用程序。

4418040-1c0a4af35d7042d1

然后按照下面提到的步骤逐一构建和测试由内存缓存提供的各种功能。

1. 内存缓存需要在启动类 Startup 中启用一下

不同于 ASP.NET Web 窗体和 ASP.NET MVC,ASP.NET Core 没有内置的 Cache 对象,可以拿来在控制器里面直接使用。 这里,内存缓存时通过依赖注入来启用的,因此第一步就是在 Startup 类中注册内存缓存的服务。如此,就得打开 Startup 类然后定位到 ConfigureServices() 方法,像下面这样修改 ConfigureServices() 方法:

publicvoidConfigureServices(IServiceCollection services){    services.AddMvc();        services.AddMemoryCache();}

为了向你的应用程序加入内存缓存能力,你需要在服务集合上调用 AddMemoryCache() 方法。采用这种办法就可以让一个内存缓存(它是一个 IMemoryCache 对象)的默认实现可以被注入到控制器中去。

2. 内存缓存使用依赖注入来注入缓存对象

然后打开 HomeController 并对其进行修改,如下所示:

publicclassHomeController:Controller{privateIMemoryCache cache;publicHomeController(IMemoryCache cache){this.cache = cache;    }    ....}

如你所见,上述代码声明了一个 ImemoryCache 的私有变量。该变量会被构造器中被赋值。构造器会通过 DI(依赖注入)接收到缓存参数,然后被存储在本地变量总,提供后续使用。

3. 你可以使用 Set() 方法来在缓存中存东西

等你有了这个 IMemoryCache 对象,就可以读取或者向它写入数据了。向缓存写入数据项是相当直接的。

publicIActionResultIndex(){  cache.Set("timestamp", DateTime.Now.ToString());returnView();}

上述代码在 Index() 这个 action 中设置了一个缓存项。这是通过使用 IMemoryCache 的 Set() 来完成的。Set() 方法的第一个参数是键名,用来标识该数据项。第二个参数是键的取值。在此例中,我们存储一个字符串的键和一个字符串的值,而你也可以存储其它类型 (原生以及自定义的类型) 的键值对。

4. 你可以使用 Get 方法来从缓存中获取到一个数据项

等你向缓存中添加好了数据,也许会想要在应用程序的其它地方去获取到该数据,可以用 Get() 来做到。如下代码会告诉你如何来做这件事情。

public IActionResultShow(){stringtimestamp= cache.Get("timestamp");  return View("Show",timestamp);

}

上述代码从 HomeController 的另外一个action(Show)那里获取到了一个缓存的数据项。Get() 方法会指定数据项的类型以及它的键名。如果该数据项存在的话,就会被返回并且被赋值给 timestamp 这个字符串变量。然后这个 timestamp 的值就会被传递给 Show 视图。

Show 视图只是简单地输出了 timestamp 的值,如下所示:

TimeStamp : @Model

@Html.ActionLink("Go back","Index","Home")

为了对目前为止你所写的代码进行一下测试,请运行应用程序。首先将浏览器导航至 /Home/Index ,这样 timestamp 键就会被赋值。然后导航至 /Home/Show 并查看 timestamp 值是否会输出。下图所示是 Show() 这个 action 运行起来的一个例子。

4418040-c5506b503ae2b18f.gif

5. 你可以使用 TryGet() 来检查缓存中是否存在特定的键值

如果你观察前面的示例,会发现每次你导航至 /Home/Index 的时候, 都会有一个新的 timestamp 被赋值给了缓存项。这是因为我们并没有对此进行检查,规定只有在数据项不存在的时候才赋值。许多时候你都会想要这样做的。这里有两种办法可以在 Index() 这个 action 里面来做这样的检查。我们把两种办法都在下面列了出来。

//first wayif(string.IsNullOrEmpty(cache.Get("timestamp"))){  cache.Set("timestamp", DateTime.Now.ToString());}//second wayif(!cache.TryGetValue("timestamp",outstringtimestamp)){    cache.Set("timestamp", DateTime.Now.ToString());}

第一种办法使用了你早先用过的同一个 Get() 方法,这一次它被拿来跟 if 块一起用。如果 Get() 不能在缓存中找到指定的数据项,IsNullOrEmpty() 就会返回 true。而只有这时候 Set() 才会被调用,一次来添加数据项。

第二种办法更加优雅一点。它使用 TryGet() 方法来获取一个数据项。TryGet() 方法会返回一个布尔值来指明数据项有没有被找到。实际的数据项可以使用一个输出参数拉取出来。如果 TryGet() 返回false,Set() 就会被用来添加数据。

6. 如果不存在的话,可以使用 GetOrCreate() 来添加一项

有时你需要从缓存中检索现有项。如果该项目不存在,则希望添加该项。这两个任务 - 如果它存在获取值,否则创建之 - 可以使用 GetOrCreate() 方法来实现。修改后的 Show() 方法展示了如何实现的。

publicIActionResultShow(){stringtimestamp = cache.GetOrCreate  ("timestamp", entry => {returnDateTime.Now.ToString(); });returnView("Show",timestamp);}

Show() 动作现在使用 GetOrCreate() 方法。 GetOrCreate() 方法将检查时间戳的键值是否存在。如果是,现有值将被赋值给局部变量。否则,将根据第二个参数中指定的逻辑创建一个新条目并将其添加到缓存中。

为了测试此代码,请直接运行 /Home/Show,不需要跳转到 /Home/Index。你仍然会看到输出的时间戳值,因为在该值不存在的情况下,GetOrCreate() 现在是添加了它。

7. 你可以在一个缓存的数据项上面设置绝对和滚动的过期时间

在前述示例中,一个缓存项只要被添加到缓存就会一直存储,除非它被明确地使用 Remove() 从缓存中移除。你也可以在一个缓存项上面设置一个绝对和滚动的过期时间。一个绝对的过期设置意味着该缓存项会在严格指定的日期和时间点被移除,而滚动过期设置则意味着它在给定的一段时间量处于空闲状态(也就是没人去访问)之后被移除。

为了能在一个缓存项上面设置这两种过期策略,你要用到 MemoryCacheEntryOptions 对象。如下代码向你展示了如何去使用。

MemoryCacheEntryOptions options =newMemoryCacheEntryOptions();options.AbsoluteExpiration = DateTime.Now.AddMinutes(1);options.SlidingExpiration = TimeSpan.FromMinutes(1);cache.Set("timestamp", DateTime.Now.ToString(), options);

上述代码来自于修改过的 Index() action,它创建了一个 MemoryCacheEntryOptions 的对象,然后将它的 AbsoluteExpiration 属性设置为从此刻到一分钟之后的一个 DateTime 值,它还将 SlidingExpiration 属性设置为一分钟。这些值都指定了该缓存项会在一分钟之后从缓存移除,不管其是否会被访问。此外,如果该缓存项如初持续空闲了有一分钟,它也会被从缓存中移除。

等你将 AbsoluteExpiration 和 SlidingExpiration 的值设置后, Set() 方法就可以被用来将一个数据项添加到缓存。这一次 MemoryCacheEntryOptions 对象会被作为第三个参数传递给 Set() 方法。

8. 当缓存项会被移除时,你可以连接回调

有时你会想要在缓存项从缓存中被移除时收到通知。可能会有多种原因需要从缓存中移除数据项。例如,因为明确地执行了 Remove() 方法而移除了一个缓存项, 也有可能是因为它的 AbsoluteExpiration 和 SlidingExpiration 值已经到期而被移除,诸如此类的原因。

为了能知道项目是何时从缓存移除的,你需要编写一个缓存函数。如下代码向你展示了如何去做这件事情:

MemoryCacheEntryOptions options =newMemoryCacheEntryOptions();options.AbsoluteExpiration = DateTime.Now.AddMinutes(1);options.SlidingExpiration = TimeSpan.FromMinutes(1);options.RegisterPostEvictionCallback(MyCallback,this);cache.Set("timestamp", DateTime.Now.ToString(), options);

上述代码同之前使用 MemoryCacheEntryOptions 来配置 AbsoluteExpiration 和 SlidingExpiration 的代码相当类似。更加重要的是它也调用了 RegisterPostEvictionCallback() 方法来绑定刚刚讨论过的回调函数。在这里回调函数被命名为 MyCallback。第二个参数是一个你会想要传递给回调函数的状态对象。这里我们传入了 HomeController 的实例 (用 this 将当前的 HomeController 对象“点”出来) 作为状态对象。

前面提到的MyCallback函数,其代码如下所示:

privatestaticvoidMyCallback(objectkey,objectvalue,EvictionReason reason,objectstate){varmessage = $"Cache entry was removed : {reason}";    ((HomeController)state).cache.Set("callbackMessage", message);}

请仔细观察这段代码。 MyCallback() 是 HomeController 类里面的一个私有静态函数,它有四个参数。前面两个参数表示刚刚删除的缓存项的键和值,第三个参数表示的是该数据项被删除的原因。EvictionReason 是一个枚举类型,它维护者各种可能的删除原因,如过期,删除以及替换。

在回调函数的内部,我们会基于删除的原因构造一个字符串消息。我们想要将此消息设置成另外一个缓存项。这样做的话就需要访问 HomeController 的缓存对象,此时状态参数就可以排上用场了。使用状态对象,你可以对 HomeController 的缓存对象进行控制,并使用 Set() 增加一个 callbackMessage 缓存项。

你可以通过 Show() 这个 action 来访问到 callbackMessage,如下所示:

public IActionResultShow(){stringtimestamp= cache.Get("timestamp");  ViewData["callbackMessage"] =    cache.Get("callbackMessage");  return View("Show",timestamp);

}

最后就可以在 Show 视图中显示出来了:

TimeStamp : @Model

@ViewData["callbackMessage"]

@Html.ActionLink("Go back","Index","Home")

欢迎关注我的公众号(同步更新文章)DoNet技术分享平台

阅读原文

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/272640.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

两张趣图助你理解状态码的含义~

HTTP状态码(HTTP Status Code)是用以表示网页服务器HTTP响应状态的3位数字代码。我们可以通过查看HTTP状态码来判断服务器状态,常见的有404 、502等;但是其他不是很常见的状态码都代表什么状态呢?下面有两张有趣的图片…

产品经理必备神器推荐

欢迎关注我的公众号(同步更新文章):DoNet技术分享平台阅读原文工欲善其事,必先利其器,作为最追求极致体验的产品经理群体,手里有一件趁手的法器,工作起来才会有一种享受般的快感,最近…

JS关闭浏览器 (不弹出提示框)

如果网页不是通过脚本程序打开的(window.open()),调用window.close()脚本关闭窗口前,必须先将window.opener对象置为null,否则浏览器(IE7、IE8)会弹出一个确定关闭的对话框。<script…

AM335x(TQ335x)学习笔记——GPIO关键驱动移植

或按照S5PV210学习秩序。我们首先解决的关键问题。TQ335x有六个用户按钮,每个上、下、剩下、对、Enter和ESC。我想开始学习S5PV210当同一,写输入子系统驱动器的关键问题要解决,但浏览driver/input/keyboardgpio-keys.c,大体上看下…

程序员偷偷深爱的9个不良编程习惯

新媒体管家下面这9个编码习惯,虽然在编程规则中是被驳斥的,但我们很多人就是会不由自主地使用它们。我们曾经都做过这样的事情:当妈妈不注意的时候,偷偷地吃糖果零食,然后导致有了蛀牙。同样的,我们都违背过…

emacs c语言 自动补全,Emacs 与 C/C++ 代码自动补全

基于 Emacs 的 company 模式并配合 semantic 文法分析器,实现 Emacs 的 C/C 代码自动补全。关于 Emacs 的代码自动补全代码自动补全的功能,对于使用 Emacs 写代码的程序员而言其重要性不言而喻的,但是搜了一些所谓的 “Emacs 完美的 C 自动补…

c语言一元二次方程 ii(分支嵌套),C程序设计——求一元二次方程算法

要求:从键盘上输入一元二次方程的三个参数,编程判断并求一元二次方程的实根(a,b,c均为整数)算法分析:一元二次方程是只含有一个未知数,且未知数的最高次数是二次的多项式方程。一元二次方程经过整理都可化成一般形式axbxc0(a≠0)&…

程序员如何优雅度过一生的15个建议

首先,我要说明一下精彩的职业生涯应该是什么样。他们不是这样的一个线性图形,不是每过一个月你就会有对应的成长。(就算是普通的职业生涯也不会这样。你不会每个月都有提升。每个月你都会变的好一点,但是每次有提升都是大幅度的&a…

cocos2d-x游戏开发 跑酷(四) 关联与物理世界

原创。转载注明出处http://blog.csdn.net/dawn_moon/article/details/21451077 前面一节尽管实现了一个跑动的人物,可是他只不过一个精灵在运行一个跑动的帧动画而已。这一节我要实现精灵和物理世界关联。让这个人跟实际的Parkour一样,有实际体积&#x…

MyBatis多条件查询

1.MyBatis多条件查询1.1&#xff1a;使用实体类 将参数封装成对象接口&#xff1a;public List<User> getUserListByUser(User user);Mapper映射文件&#xff1a;<select id"getUserListByUser" resultType"User" parameterType"User"…

android蓝牙移植,平板蓝牙测试与移植一

一&#xff0e;平板蓝牙测试硬件连接&#xff1a;进入系统的”设置”&#xff0c;开启“蓝牙”&#xff1a;可以看到扫描到其他的蓝牙设备&#xff0c;“Bluez”是平板的名称。点击“Bluez”&#xff0c;设置如下&#xff1a;点击要配对的蓝牙设备(手机等)&#xff0c;进行蓝牙…

ASP.NET系列:自定义配置节点的复用

appSettings太简单&#xff0c;为每个程序自定义配置节点太复杂&#xff0c;因此要解决app.config&web.config自定义配置的复用问题。 1.读取不依赖SectionName,根节点可以定义为任何名称。 2.足够简单&#xff0c;配置项采用name value的形式&#xff1b;足够复杂&#xf…

Web的26项基本概念和技术

Web开发是比较费神的&#xff0c;需要掌握很多很多的东西&#xff0c;特别是从事前端开发的朋友&#xff0c;需要通十行才行。今天&#xff0c;本文向初学者介绍一些Web开发中的基本概念和用到的技术&#xff0c;从A到Z总共26项&#xff0c;每项对应一个概念或者技术。Internet…

BZOJ3670: [Noi2014]动物园

Description 近日&#xff0c;园长发现动物园中好吃懒做的动物越来越多了。例如企鹅&#xff0c;只会卖萌向游客要吃的。为了整治动物园的不良风气&#xff0c;让动物们凭自己的真才实学向游客要吃的&#xff0c;园长决定开设算法班&#xff0c;让动物们学习算法。 某天&#x…

android one指纹解锁,小米用屏幕内指纹扫描仪准备了两部Android One手机

2017年9月发布时&#xff0c;小米米A1几乎成功一夜成名。小西米去年夏天推出了Mi A2和Mi A2 Lite。现在&#xff0c;正如XDA开发者所揭示的那样&#xff0c;中国品牌正在筹备第三代产品阵容。代号为“bamboo_sprout”和“cosmos_sprout” - 所有Android One智能手机都包含代号为…

控制算法用c语言实现的,PID控制算法的C语言实现(完整版)

【实例简介】该文件里面还有各种改进的PID的算法&#xff0c;比如变积分控制等【实例截图】【核心代码】具体 PID 实现代码如下&#xff1a;pid.Kp0.4;pid.Ki0.2;//增加了积分系数pid.Kd0.2;float PID_realize(float speed){float index;pid.SetSpeedspeed;pid.errpid.SetSpeed…

easyui dialog的一个小坑

问题描述&#xff1a;1、html<div id"dig" style"padding:10px;width:500px;height:300px;font-family:微软雅黑;font-size:16px;"> Dialog Content. </div> 2、js$("#dig").css("display", "block");$(#dig).d…

C# 如何转换生成长整型的时间

这个数字字符串就是我们平常所说的时间戳。什么是时间戳&#xff1f;时间戳&#xff08;timestamp&#xff09;&#xff0c;通常是一个字符序列&#xff0c;唯一地标识某一刻的时间。时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至…

html自动滑动轮播代码,html+css+js 实现自动滑动轮播图

轮播图*{margin: 0 auto;padding: 0;list-style: none; //去圆点}.one {width: 1200px;height:350px;margin: 0 auto;overflow: hidden; //设定好的宽度多余的进行隐藏}.one ul{width: 3600px;position: relative;}.one ul li{float: left; //图片浮动}.two ul li { …

程序员必定会爱上的10款软件

目录 第一款&#xff1a;TrueCrypt 第二款&#xff1a;Soureinsight 第三款&#xff1a;Sublime 第四款&#xff1a;Mindmanager 第五款&#xff1a;MarkdownPad 第六款&#xff1a;Beyond compare 第七款&#xff1a;Vim 第八款&#xff1a;Wireshark 第九款&#xff1a;Fiddl…