ABP框架 - 缓存
本节内容:
简介
ABP提供了一个缓存接口,它内部使用了这个缓存接口。虽然接口的默认实现是MemoryCache,但可以用任何其它实现的缓存供应器。Abp.RedisCache包用Redis实现了缓存(查看下方的“Redis 缓存集成”)。
ICacheManager
缓存的主要接口是ICacheManager。我们可以注入它并用它获取一个缓存,如:
public class TestAppService : ApplicationService
{
private readonly ICacheManager _cacheManager; public TestAppService(ICacheManager cacheManager)
{
_cacheManager = cacheManager;
} public Item GetItem(int id)
{
//Try to get from cache
return _cacheManager
.GetCache("MyCache")
.Get(id.ToString(), () => GetFromDatabase(id)) as Item;
} public Item GetFromDatabase(int id)
{
//... retrieve item from database
}
}
在此例里,我们注入了ICacheManager,并获得一个名为MyCache的缓存。
警告:GetCache方法
如果你的类不是单例,不要在你构造器里使用GetCache,否则可能会销毁你的缓存。
ICache
ICacheManager.GetCache方法返回一个ICache。一个缓存是单例的(每个缓存名)。第一次请求时创建,然后一直返回同一个缓存对象。所以,我们可以在不同的类(客户端)里用相同的名字共享同一个缓存。
在示例代码里,我们看到了ICache.get方法的简单使用。它有两个参数:
key:字符串,必需,一个缓存项的键。
factory:一个action(行为),在找不到指定key的缓存项时调用,Factory方法应该创建并返回切实的项,如果指定key的缓存已存在,就不调用。
ICache接口也有如GetOrDefault、Set、Remove和Clear等方法。同样也有async版本。
ITypedCache
ICache接口以字符串为key,值是object类型。ITypedCache包装了ICache并提供了类型安全、泛型。我们可用泛型的GetCache扩展方法,获取一个ITypedCache:
ITypedCache<int, Item> myCache = _cacheManager.GetCache<int, Item>("MyCache");
同样,我们也可用AsTyped扩展方法,把一个已存在的ICache实例转换成ITypedCache。
配置
默认缓存超时是60分钟,它可以改。如果你超过60分钟没有使用缓存中的项,会从缓存中自动移除。你可以配置指定的缓存或是全部的缓存。
//Configuration for all caches
Configuration.Caching.ConfigureAll(cache =>
{
cache.DefaultSlidingExpireTime = TimeSpan.FromHours();
}); //Configuration for a specific cache
Configuration.Caching.Configure("MyCache", cache =>
{
cache.DefaultSlidingExpireTime = TimeSpan.FromHours();
});
这段代码应该写在你模块的PreInitialize方法里,用这段代码,MyCache将有8个小时的超时时间,其它的缓存有2个小时。
在第一次创建缓存(在第一次请求)调用你的配置行为。配置不是只有DefaultSlidingExpireTime,由于缓存对象是一个ICache,所以你可以用它的属性和方法,自由的配置和初始化。
实体缓存
虽然ABP缓存系统出于普通的目的,但有一个EntityCache基类,可帮你缓存实体。如果我们通过它们的Id获取的实体,我们可以用这个基类缓存它们,就不用再频繁地从数据库查询。假设我们有如下所示的一个person实体:
public class Person : Entity
{
public string Name { get; set; } public int Age { get; set; }
}
并假设我们已经知道Id,要频繁地获取Name。首先,我们需要创建一个类来缓存项:
[AutoMapFrom(typeof(Person))]
public class PersonCacheItem
{
public string Name { get; set; }
}
我们不应该直接在缓存里存储实体,由于缓存可能需要序列化缓存对象,而实体不一定能序列化(尤其有导航属性的实体)。这就是为什么我们创建一个简单(像DTO:数据传输对象)类存储数据。添加AutoMapFrom特性,它可以自动地把Person转换成PersonCacheItem对象。如果我们不使用AutoMapFrom,我们应该为重载EntityCache类的MapToCacheItem方法,手动转换/映射。
虽然不是必需,但我们可能想为我们的缓存类定义一个接口:
public interface IPersonCache : IEntityCache<PersonCacheItem>
{ }
最后,我们可以为实体创建缓存类:
public class PersonCache : EntityCache<Person, PersonCacheItem>, IPersonCache, ITransientDependency
{
public PersonCache(ICacheManager cacheManager, IRepository<Person> repository)
: base(cacheManager, repository)
{ }
}
这就是全部代码,我们的Person缓存已经可用。缓存类可以是暂时的(如示例)或单体的,这不是说缓存的数据是暂时的,它始终在你的应用里是全局的并线程安全的。
现在,任何需要Person的Name时,我们可以通过person的Id从缓存获取,使用Person缓存的示例如下:
public class MyPersonService : ITransientDependency
{
private readonly IPersonCache _personCache; public MyPersonService(IPersonCache personCache)
{
_personCache = personCache;
} public string GetPersonNameById(int id)
{
return _personCache[id].Name; //alternative: _personCache.Get(id).Name;
}
}
我们简单地注入IPersonCache,获取缓存项和获取Name属性。
EntityCache 是如何工作
- 在第一个调用里获取从仓储(从数据库)获取实体,然后在接下来的调用里从缓存里获取。
- 如果实体更新或删除后,它自动使缓存失效,所以它将在下一个调用里重新从数据库获取。
- 使用IObjectMapper映射到缓存项,AutoMpper模块实现了IObjectMapper,所以需要AutoMapper模块。你可以重载MapToCacheItem方法,手动映射实体到缓存项。
- 使用缓存类全名作为缓存时的名称,你可以通过传递一个缓存名给基构造器来改变它。
- 是线程安全的。
如果你需要更复杂的缓存技术,你可以扩展EntityCache或创建你自己的解决方案。
Redis 缓存集成
默认缓存管理使用的是内存缓存。所以,如果你有多个并发的Web服务器使用同个应用,可能会成为一个问题,在这种情况下,你需要一个分布/集中缓存服务,你就可以简单的使用Redis做为你的缓存服务器。
首先,你要在你的应用里,安装Abp.RedisCache的Nuget包(例如,你可在你的Web项目里安装)。接着为AbpRedisCacheModule添加DependsOn特性,然后在你模块预初始化方法里调用useRedis扩展方法。如下所示:
//...other namespaces
using Abp.Runtime.Caching.Redis; namespace MyProject.AbpZeroTemplate.Web
{
[DependsOn(
//...other module dependencies
typeof(AbpRedisCacheModule))]
public class MyProjectWebModule : AbpModule
{
public override void PreInitialize()
{
//...other configurations Configuration.Caching.UseRedis();
} //...other code
}
}
Abp.RedisCache包使用”localhost“作为默认连接字符串,你可以在配置文件里添加连接字符串重写它,例如:
<add name="Abp.Redis.Cache" connectionString="localhost"/>
同样,你可以向appSettings里添加Redis的数据库Id,例如:
<add key="Abp.Redis.Cache.DatabaseId" value=""/>
不同的数据库Id,在同一服务器上,帮助创建不同的键空间(独立缓存)。
UseRedis方法也有一个重载,用给定的action(行为)直接设置选项值(在配置文件中重写)。
查看更多有关Redis信息及它的配置,请查阅Redis文档。
提醒:Redis服务器应该安装和运行在ABP里。
ABP框架 - 缓存的更多相关文章
- ABP框架 - 缓存( 转)
出处:http://www.cnblogs.com/kid1412/p/5987083.html 文档目录 本节内容: 简介 ICacheManager ICache ITypedCache 配置 实 ...
- ABP开发框架前后端开发系列---(15)ABP框架的服务端和客户端缓存的使用
缓存在一个大型一点的系统里面是必然会涉及到的,合理的使用缓存能够给我们的系统带来更高的响应速度.由于数据提供服务涉及到数据库的相关操作,如果客户端的并发数量超过一定的数量,那么数据库的请求处理则以爆发 ...
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十五节--缓存小结与ABP框架项目中 Redis Cache的实现
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 缓存 为什么要用缓存 为什么要用缓存呢,说缓存之前先说使用缓存的优点. 减少寄宿服务器的往返调用(round-tr ...
- 一步一步使用ABP框架搭建正式项目系列教程之本地化详解
返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...
- ABP框架详解(七)Caching
在ABP框架中存在一个缓存机制,使用ICache的继承类来存储最终需要缓存的数据,可以吧ICache看成一个字典对象,使用Key作为真实数据的具有唯一性的表示.使用上与字典对象完全相同,Get方法传递 ...
- ABP框架详解(五)Navigation
ABP框架中的Navigation功能用于管理业务系统中所有可用的菜单导航控件,通常在业务系统的首页会有一个全局性的导航菜单,JD商城,天猫,猪八戒网莫不如是.所以为方便起见,Navigation功能 ...
- ABP框架详解(二)AbpKernelModule
AbpKernelModule类是Abp框架自己的Module,它也跟所有其他的Module一样继承自AbpModule,重写PreInitialize,Initialize,PostInitiali ...
- ABP框架 - N层架构
目录 介绍 DDD分层 ABP架构模型 客户端 展现层 分布式服务层 应用层 领域层 基础设施层 介绍 在应用程序设计中,分层架构是一种被广泛使用的技术,它助于降低复杂度和提高代码的可重用性.在ABP ...
- [Abp 源码分析]一、Abp 框架启动流程分析
Abp 不一定仅用于 Asp.Net Core 项目,他也可以在 Console 与 WinFrom 项目当中进行使用,所以关于启动流程可以分为两种,一种是 Asp.Net Core 项目的启动流程, ...
随机推荐
- 前端框架 EasyUI (1)熟悉一下EasyUI
jQuery EasyUI 官方网站 http://www.jeasyui.com/ .去年新开了个中文网 http://www.jeasyui.net/,不知道是不是官方的,不过看着挺像样.但是,广 ...
- 【组织级项目管理】P2 MSP P3O
组织级项目管理--有你,有我,有大家 在过去的2年,无论对于企业来讲,还是对于我们个人都有很多大脑的冲击,有几个词大家应该特别耳熟能详:转型,变革,敏捷,互联网+,组织的项目化管理等.就是这些让我们的 ...
- Asp.Net MVC中使用StreamReader读取“Post body”之应用场景。
场景:有三个市场(Global.China.USA),对前台传过来的数据有些验证需要细化到每个市场去完成. 所以就出现了基类(Global)和派生类(China.USA) 定义基类(Global)Pe ...
- 11、Struts2 的文件上传和下载
文件上传 表单准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设置 ...
- WPF样式之画刷结合样式
第一种画刷,渐变画刷GradientBrush (拿线性渐变画刷LinearGradientBrush(其实它涵盖在GradientBrush画刷内.现在拿他来说事.),还有一个圆心渐变画刷Radia ...
- 调用微信退款接口或发红包接口时出现System.Security.Cryptography.CryptographicException: 出现了内部错误 解决办法
我总结了一下出现证书无法加载的原因有以下三个 1.证书密码不正确,微信证书密码就是商户号 解决办法:请检查证书密码是不是和商户号一致 2.IIS设置错误,未加载用户配置文件 解决办法:找到网站使用的应 ...
- interpreter(解释器模式)
一.引子 其实没有什么好的例子引入解释器模式,因为它描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发编译器中:在实际应用中,我们可能很少碰到去构造一个语言的文法的情况. 虽然你几乎用 ...
- git和pycharm管理代码
首先明白三个概念,服务器代码库,本地代码库,和正在coding的项目. coding完毕后,先通过commit提交到本地代码库,然后通过push再提交server的代码库 git步骤 git c ...
- UGUI Text(Label)
环境 Unity 5.3.6f1 关于Best Fit 如果勾选了 Best Fit ,当有大量的文本填充在Text上时,那么文字是不会自动换行的. 打字机效果 在github上已有现成的:https ...
- 【腾讯优测干货分享】如何降低App的待机内存(三)——探索内存增长的原因
本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/8BiKIt3frq9Yv9KV5FXlGw 1.3新问题的进一步挖 ...