ABP官方文档翻译 2.3 缓存
缓存
介绍
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的缓存。缓存名称是大小写敏感的,意味着“MyCache”和“MYCACHE”是不同的缓存。
警告:GetCache方法
不要在构造函数中使用GetCache。如果类不是单例的话,缓存可能会被释放。
ICache
ICacheManager.GetCaChe方法返回ICache。缓存是单例的(每个缓存名称)。首次需要的时候创建,然后每次都返回同样的缓存对象。所以,我们可以在不同的类(客户端)使用相同的名字共享同样的缓存。
在实例代码中,我们看到了ICache.Get方法的简单使用。它有两个参数:
- Key:缓存中一个项的唯一字符串键。
- factory:如果指定的键没有项目时调用。工厂方法应该创建并返回真实的项。如果指定的键在缓存中存在的话就不会调用这个方法。
ICache接口也有如GetOrDefault,Set,Remove和Clear这样的方法。同样也有这些方法的异步版本。
ITypedCache
ICache接口使用string类型作为键,object作为值。ITypeCache是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基类。如果我们通过Ids获取到实体并且想通过Id缓存实体而不是经常从数据库查询,我们就可以使用这个基类。假如我们有一个Person实体,如下:
public class Person : Entity
{
public string Name { get; set; } public int Age { get; set; }
}
假如我们知道Id并想以此获取people的Name。首先,我们创建一个类储存缓存项:
[AutoMapFrom(typeof(Person))]
public class PersonCacheItem
{
public string Name { get; set; }
}
不应该直接在缓存中直接存储实体,因为缓存可能需要序列化缓存的对象,实体可能不能被序列化(尤其是有导航属性时)。这就是我们在缓存中定义一个简单类(像DTO)存储数据的原因。因为我们想使用AutoMapper自动将Person实体转换为PersonCahcedItem,所以在类上添加了AutoMapFrom特性。如果我们不使用AutoMapper,那需要重写EntityCache类的MapToCacheItem方法来实现自动转换或映射。
我们希望定义一个缓存类的接口,虽然这不是必须的:
public interface IPersonCache : IEntityCache<PersonCacheItem>
{ }
最后,我们可以创建缓存类缓存Person实体了:
public class PersonCache : EntityCache<Person, PersonCacheItem>, IPersonCache, ITransientDependency
{
public PersonCache(ICacheManager cacheManager, IRepository<Person> repository)
: base(cacheManager, repository)
{ }
}
就这样,我们的person缓存可以使用了。Cache类可以是临时的(如本例)也可以是单例的。这并不意味着缓存数据是临时的。在应用中,它总是全局缓存并且访问是线程安全的。
现在,不管何时我们需要person的Name时,我们可以通过person`s 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属性。
实体缓存如何工作
- 在首次调用时,从仓储(从数据库)获取实体。然后在之后的调用从缓存获取。
- 如果实体被更新或删除,会自动使缓存实体无效。然后,在下次调用时会从数据库中重新获取。
- 使用IObjectMapper映射实体和缓存项。IObjectMapper通过AutoMapper模块实现。所以,如果使用的话需要AutoMapper模块。可以重写MapToCacheItem方法手动映射实体和缓存项。
- 使用缓存类FullName作为缓存名称。可以通过向基类构造函数传递缓存名称来改变它。
- 线程安全。
如果需要更复杂的缓存,可以扩展EntityCache或创建自己的解决方案。
Redis缓存集成
默认的缓存管理器使用内存缓存。所以,如果有多于一个并发网络服务器运行同样的应用,将会成为一个问题。在这种情况下,需要使用一个分布式/中央缓存服务器。可以很简单的使用Redis作为缓存服务器。
首先,需要在应用(例如,可以安装在Web工程)中安装Abp.RedisCache nuget包。然后,需要需要给AbpRedisCacheModule添加DependsOn特性,并在模块的PreInitialize方法中调用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=""/>
在同一个服务器中,不同的数据库ids用来创建不同的关键空间(隔离缓存)。
UseRedis方法有个重载,可以用来直接设置选项值(在配置文件中重写值)。
参见Redis文档获取关于Redis及配置的更多信息。
注意:Redis服务器应该安装并运行,以便在ABP中使用Redis缓存。
ABP官方文档翻译 2.3 缓存的更多相关文章
- ABP官方文档翻译 10.1 ABP Nuget包
ABP Nuget包 Packages Abp Abp.AspNetCore Abp.Web.Common Abp.Web Abp.Web.Mvc Abp.Web.Api Abp.Web.Api.OD ...
- 0.0 ABP官方文档翻译目录
一直想学习ABP,但囿于工作比较忙,没有合适的契机,当然最重要的还是自己懒.不知不觉从毕业到参加工作七年了,没留下点儿什么,总感觉很遗憾,所以今天终于卯足劲鼓起勇气开始写博客.有些事能做的很好,但要跟 ...
- ABP官方文档翻译 2.5 设置管理
设置管理 介绍 关于 ISettingStore 定义设置 设置范围 重写设置定义 获取设置值 服务端 客户端 更改设置 关于缓存 介绍 每个应用都需要存储设置,并且在应用的某些地方需要使用这些设置. ...
- ABP官方文档翻译 6.2.1 ASP.NET Core集成
ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Acti ...
- ABP官方文档翻译 5.1 Web API控制器
ASP.NET Web API控制器 介绍 AbpApiController基类 本地化 其他 过滤器 审计日志 授权 反伪造过滤器 工作单元 结果包装和异常处理 结果缓存 校验 模型绑定器 介绍 A ...
- ABP官方文档翻译 0.0 ABP官方文档翻译目录
一直想学习ABP,但囿于工作比较忙,没有合适的契机,当然最重要的还是自己懒.不知不觉从毕业到参加工作七年了,没留下点儿什么,总感觉很遗憾,所以今天终于卯足劲鼓起勇气开始写博客.有些事能做的很好,但要跟 ...
- ABP官方文档翻译 1.5 多租户
多租户 什么是多租户? 数据库和部署架构 多部署-多数据库 单部署-多数据库 单部署-单数据库 单部署-混合数据库 多部署-单/多/混合数据库 ABP的多租户 启用多租户 租主和租户 会话 决定当前租 ...
- ABP官方文档翻译 9.3 NHibernate集成
NHibernate集成 Nuget包 配置 实体映射 仓储 默认实现 自定义仓储 应用程序特定基础仓储类 ABP可以使用任何ORM框架,它内置集成NHibernate.此文档将讲解ABP如何使用NH ...
- ABP官方文档翻译 9.2 Entity Framework Core
Entity Framework Core 介绍 DbContext 配置 在Startup类中 在模块PreInitialize方法中 仓储 默认仓储 自定义仓储 应用程序特定基础仓储类 自定义仓储 ...
随机推荐
- bzoj 3065: 带插入区间K小值(分块)
Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它 ...
- Gym 100952H&&2015 HIAST Collegiate Programming Contest H. Special Palindrome【dp预处理+矩阵快速幂/打表解法】
H. Special Palindrome time limit per test:1 second memory limit per test:64 megabytes input:standard ...
- BZOJ 1257: [CQOI2007]余数之和sum【神奇的做法,思维题】
1257: [CQOI2007]余数之和sum Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 4474 Solved: 2083[Submit][St ...
- [bzoj3191] [JLOI2013]卡牌游戏
概率DP. 首先由题解可得>_<,胜出概率只与剩余人数.与庄家的相对位置有关. 所以设f[i][j]表示剩下i个人,从庄家开始第j个人的胜利概率... 根据卡牌一通乱搞即可... #inc ...
- codeforce 375_2_b_c
codeforce 375_2 标签: 水题 好久没有打代码,竟然一场比赛两次卡在边界条件上....跪 b.题意很简单...纯模拟就可以了,开始忘记了当字符串结束的时候也要更新两个值,所以就错了 #i ...
- 用.net中的SqlBulkCopy类批量复制数据 (转载)
在软件开发中,把数据从一个地方复制到另一个地方是一个普遍的应用. 在很多不同的场合都会执行这个操作,包括旧系统到新系统的移植,从不同的数据库备份数据和收集数据. .NET 2.0有一个SqlBulkC ...
- 浏览器与CDN缓存行为
@地址栏回车 1. 未过期: 浏览器拦截,直接返回: (expires/cache-control两个参数决定,如果两个参数都有,cache-control覆盖expires); 2. 已过期: et ...
- 为了解决linux配置Nginx 只能关闭防火墙才能访问的问题
使用Nginx和iptables做访问权限控制(IP和MAC) 之前配置的服务器,相当于对整个内网都是公开的,而且,除了可以通过80端口的nginx来间接访问各项服务,也可以绕过nginx,直 ...
- PHP error_reporting() 错误控制函数功能详解
定义和用法: error_reporting() 设置 PHP 的报错级别并返回当前级别. 函数语法: error_reporting(report_level) 如果参数 level 未指定 ...
- WEBZIP为什么打不开网页
先试三个办法 一.打开IE,点工具,点internet选项,点高级,点恢复默认设置,点保存,退出,重新打开IE 二.打开IE,刷新五次以上 三.打开IE,点工具,点internet选项,点删除文件,点 ...