ABP之Caching
简介
ABP提供缓存抽象,默认使用MemoryCache。但是可以替换成其他缓存程序,比如 Abp.RedisCache 是使用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”是两个不同的缓存。
ICache
ICacheManager.GetCache返回一个ICache,缓存是单例的,是在第一次请求被创建,然后总是返回相同的对象。通过这种方式,我们可以在不同的类(客户端)中使用相同的名称共享相同的缓存。
在示例代码中,我们看到了ICache.Get的简单用法,它有两个参数,
- key:缓存中项的唯一键(字符串)。
- factory:如果没有具有给定键的Item,则调用该Action。工厂方法应该创建并返回实际的Item。如果给定键存在于缓存中,则不调用该Action。
ICache接口还具有GetOrDefault、Set、Remove和Clear等方法,所有方法都有异步版本。
ITypedCache
ICache 接口使用字符串作为key,object对象作为value,ITypedCache是ICache的一个包装器,用于提供类型安全的通用缓存。我们可以使用通用的GetCache扩展方法来获得一个ITypedCache:
ITypedCache<int, Item> myCache = _cacheManager.GetCache<int, Item>("MyCache");
我们还可以使用AsTyped扩展方法将现有的ICache实例转换为ITypedCache。
配置
默认的缓存过期时间是60分钟,如果在60分钟之内不使用缓存中的Item,它就会被自动从缓存中删除。我们可以为所有的缓存配置过期时间,也可以为特定的缓存配置特定时间。
//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获取实体并希望通过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属性,因为我们希望使用AutoMapper将Person实体自动转换为PersonCacheItem对象。如果我们不使用AutoMapper,我们应该覆盖EntityCache类的MapToCacheItem方法来手动转换/映射它。
虽然这不是必需的,但我们最好给缓存类定义一个接口:
public interface IPersonCache : IEntityCache<PersonCacheItem>
{ }
最后,我们可以创建cache类来缓存Person实体:
public class PersonCache : EntityCache<Person, PersonCacheItem>, IPersonCache, ITransientDependency
{
public PersonCache(ICacheManager cacheManager, IRepository<Person> repository)
: base(cacheManager, repository)
{ }
}
如上所示,我们的Person缓存已准备好使用! 缓存类可以是瞬态的(如本例所示),也可以是单例的。这并不意味着缓存的数据是瞬时的。它总是全局缓存,并在应用程序中以线程安全的方式访问。
当我们想获取一个人的名字时,我们可以使用这个人的Id从缓存中获取,比如:
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将实体映射到缓存项,IObjectMapper由AutoMapper模块实现,可以覆盖MapToCacheItem方法来手动将实体映射到缓存项。
- 它使用cache类的FullName作为缓存名,可以通过将缓存名传递给基本构造函数来更改它。
- 它是线程安全的。
如果需要更复杂的缓存需求,可以扩展EntityCache或创建自己的解决方案。
Redis缓存集成
默认的缓存管理器使用内存缓存。如果有多个并发web服务器运行相同的应用程序,则可能会出现问题。在这种情况下,可能需要一个分布式/中央缓存服务器,可以使用Redis作为缓存服务器。
首先需要将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=""/>
不同的数据库id对于在同一服务器中创建不同的键空间(隔离缓存)非常有用。
UseRedis方法还有一个重载,它采取一个操作来直接设置选项值(这将覆盖配置文件中的值)。
有关Redis及其配置的更多信息,请参阅Redis文档: Redis documentation
注意:应该安装并运行Redis服务器来使用ABP中的Redis缓存。
ABP之Caching的更多相关文章
- 基于DDD的.NET开发框架 - ABP缓存Caching实现
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- ABP框架 - 缓存
文档目录 本节内容: 简介 ICacheManager ICache ITypedCache 配置 实体缓存 EntityCache 是如何工作 Redis 缓存集成 简介 ABP提供了一个缓存接口, ...
- 一步一步学习ABP项目系列文章目录
1.概述 基于DDD的.NET开发框架 - ABP初探 基于DDD的.NET开发框架 - ABP分层设计 基于DDD的.NET开发框架 - ABP模块设计 基于DDD的.NET开发框架 - ABP启动 ...
- ABP入门系列(13)——Redis缓存用起来
ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 引言 创建任务时我们需要指定分配给谁,Demo中我们使用一个下拉列表用来显示当前系统的所有用 ...
- 缓存与ABP Redis Cache
缓存与ABP Redis Cache 为什么要用缓存 为什么要用缓存呢,说缓存之前先说使用缓存的优点. 减少寄宿服务器的往返调用(round-trips). 如果缓存在客户端或是代理,将减少对服务器的 ...
- ABP官方文档翻译 2.3 缓存
缓存 介绍 ICacheManager 警告:GetCache方法 ICache ITypedCache 配置 实体缓存 实体缓存如何工作 Redis缓存集成 介绍 ABP为缓存提供了一个抽象接口,它 ...
- 使用 DryIoc 替换 Abp 的 DI 框架
一.背景 你说我 Castle Windsor 库用得好好的,为啥要大费周章的替换成 DryIoc 库呢?那就是性能,DryIoc 是一款优秀而且轻量级的 DI 框架,整个项目代码就两个文件,加起来代 ...
- ABP框架系列之十五:(Caching-缓存)
Introduction ASP.NET Boilerplate provides an abstraction for caching. It internally uses this cache ...
- ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十五节--缓存小结与ABP框架项目中 Redis Cache的实现
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 缓存 为什么要用缓存 为什么要用缓存呢,说缓存之前先说使用缓存的优点. 减少寄宿服务器的往返调用(round-tr ...
随机推荐
- Markdown 插入图片技巧
在使用Markdown编写博客或文件的时候,经常会需要插入图片.如果使用Markdown语法,我们会发现调整图片的大小会是个问题. 所以推荐使用另一种办法插入图片,使用HTML语法,示例如下: < ...
- Mac电脑上一款非常时尚高清的动态壁纸Living Wallpaper HD
很多朋友Mac电脑上都喜欢用动态壁纸,Living Wallpaper HD是本人尝试的一款非常不错的高清动态壁纸.有时钟.天气等各种组建,非常时尚美观. Living Wallpaper HD下载地 ...
- iFace Chain [ 爱妃链 ] 或将凭借人脸密钥技术成为安全领域最大的赢家
前段时间iFace Chain [ 中文音译名称: 爱妃链 ] 安全专家揭密了区块链领域,数字资产存放于无信用钱包中的一些风险,并为区块链玩家解密如何安全保护资产私钥,我们再来回顾分析一下目前跑路钱包 ...
- Linux 虚拟网络设备 veth-pair 详解,看这一篇就够了
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 前面这篇文章介 ...
- 网络协议 18 - CDN:家门口的小卖铺
[前五篇]系列文章传送门: 网络协议 13 - HTTPS 协议:加密路上无尽头 网络协议 14 - 流媒体协议:要说爱你不容易 网络协议 15 - P2P 协议:小种子大学问 网络协议 16 - D ...
- FragmentTabHostTopDemo【FragmentTabHost固定宽度且居中】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 使用FragmentTabHost实现顶部选项卡(居中且宽度非全屏)展现. 备注:该Demo主要是演示FragmentTabHost ...
- 前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战
一.组件化开发 1.1组件化概述 页面特效的制作,特别需要HTML.CSS有固定的布局,所以说现在越来越流行组件开发的模式,就是用JS写一个类,当你实例化这个类的时候,页面上的效果布局也能自动完成. ...
- Pi Hybrids问题
Pi Hybrids问题 清华大学肖秀波梁湧老师翻译的Rardin教授的<运筹学>[1]已于今年年中出版,感谢机械工业出版社张有利老师的推荐和赠书,让我能看到如此完美的千页级宏篇译著.该书 ...
- 【我们一起写框架】MVVM的WPF框架(二)—绑定
MVVM的特点之一是实现数据同步,即,前台页面修改了数据,后台的数据会同步更新. 上一篇我们已经一起编写了框架的基础结构,并且实现了ViewModel反向控制Xaml窗体. 那么现在就要开始实现数据同 ...
- Shell编程(week4_day4)--技术流ken
本节内容 1. shell函数 2. shell正则表达式 shell函数 shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数.给这段代码起个名字称为函数名,后续可以直 ...