缓存
Volo.Abp.Caching是缓存系统的核心包.使用包管理控制台(PMC)安装到项目:
然后将 AbpCachingModule 依赖添加到你的模块:
using Volo.Abp.Modularity;
using Volo.Abp.Caching;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpCachingModule))]
public class MyModule : AbpModule
{
//...
}
}
ASP.NET Core 定义了 IDistributedCache
接口用于 get/set 缓存值 . 但是会有以下问题:
- 它适用于 byte 数组 而不是 .NET 对象. 因此你需要对缓存的对象进行序列化/反序列化.
- 它为所有的缓存项提供了 单个 key 池 , 因此 ;
- 你需要注意键区分 不同类型的对象.
- 你需要注意不同租户(参见多租户)的缓存项.
ABP框架在包定义了通用的泛型 IDistributedCache<TCacheItem>
接口. TCacheItem
是存储在缓存中的对象类型.
IDistributedCache<TCacheItem>
接口了上述中的问题;
- 它在内部 序列化/反序列化 缓存对象. 默认使用 JSON 序列化, 但可以替换依赖注入系统中
IDistributedCacheSerializer
服务的实现来覆盖默认的处理. - 它根据缓存中对象类型自动向缓存key添加 缓存名称 前缀. 默认缓存名是缓存对象类的全名(如果你的类名以
CacheItem
结尾, 那么CacheItem
会被忽略,不应用到缓存名称上). 你也可以在缓存类上使用CacheName
设置换缓存的名称. - 它自动将当前的租户id添加到缓存键中, 以区分不同租户的缓存项 (只有在你的应用程序是的情况下生效). 在缓存类上应用
IgnoreMultiTenancy
attribute, 可以在所有的租户间共享缓存. - 允许为每个应用程序定义 全局缓存键前缀 ,不同的应用程序可以在共享的分布式缓存中拥有自己的隔离池.
缓存中存储项的示例类:
你可以注入 IDistributedCache<BookCacheItem>
服务用于 get/set BookCacheItem
对象.
使用示例:
public class BookService : ITransientDependency
{
private readonly IDistributedCache<BookCacheItem> _cache;
public BookService(IDistributedCache<BookCacheItem> cache)
_cache = cache;
}
public async Task<BookCacheItem> GetAsync(Guid bookId)
return await _cache.GetOrAddAsync(
bookId.ToString(), //Cache key
async () => await GetBookFromDatabaseAsync(bookId),
() => new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
}
);
}
private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
{
//TODO: get from database
}
}
- 示例服务代码中的
GetOrAddAsync()
方法从缓存中获取图书项. - 如果没有在缓存中找到图书,它会调用工厂方法 (本示例中是
GetBookFromDatabaseAsync
)从原始数据源中获取图书项. GetOrAddAsync
有一个可选参数DistributedCacheEntryOptions
, 可用于设置缓存的生命周期.
IDistributedCache<BookCacheItem>
的其他方法与ASP.NET Core的IDistributedCache
接口相同, 你可以参考 ASP.NET Core文档.
示例缓存项
用法示例 (这里假设你的键类型是 Guid
):
public class BookService : ITransientDependency
{
private readonly IDistributedCache<BookCacheItem, Guid> _cache;
public BookService(IDistributedCache<BookCacheItem, Guid> cache)
{
_cache = cache;
}
{
return await _cache.GetOrAddAsync(
bookId, //Guid type used as the cache key
async () => await GetBookFromDatabaseAsync(bookId),
{
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
}
);
}
private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
{
//TODO: get from database
}
}
- 示例服务中
GetOrAddAsync()
方法获取缓存的图书项. - 我们采用了
Guid
做为键,在_cache_GetOrAddAsync()
方法中传入Guid
类型的bookid.
IDistributedCache<TCacheItem, TCacheKey>
在内部使用键对象的 ToString()
方法转换类型为string. 如果你的将复杂对象做为键,那么需要重写类的 ToString
方法.
示例:
用法示例:
public class BookService : ITransientDependency
{
private readonly IDistributedCache<UserCacheItem, UserInOrganizationCacheKey> _cache;
public BookService(
IDistributedCache<UserCacheItem, UserInOrganizationCacheKey> cache)
{
_cache = cache;
}
...
}
ABP的分布式缓存接口定义了以下批量操作方法,当你需要在一个方法中调用多次缓存操作时,这些方法可以提高性能
SetManyAsync
和SetMany
方法可以用来设置多个值.GetManyAsync
和GetMany
方法可以用来从缓存中获取多个值.GetOrAddManyAsync
和GetOrAddMany
方法可以用来从缓存中获取并添加缺少的值.RemoveManyAsync
和RemoveMany
方法呆以用来删除多个值.
TODO