ABP提供缓存抽象,默认使用MemoryCache。可是能够替换成其余缓存程序,好比 Abp.RedisCache 是使用Redis实现缓存。web
缓存的主要接口是ICacheManager,咱们可使用它来得到缓存,好比:
redis
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”是两个不一样的缓存。数据库
ICacheManager.GetCache返回一个ICache,缓存是单例的,是在第一次请求被建立,而后老是返回相同的对象。经过这种方式,咱们能够在不一样的类(客户端)中使用相同的名称共享相同的缓存。缓存
在示例代码中,咱们看到了ICache.Get的简单用法,它有两个参数,安全
ICache接口还具备GetOrDefault、Set、Remove和Clear等方法,全部方法都有异步版本。服务器
ICache 接口使用字符串做为key,object对象做为value,ITypedCache是ICache的一个包装器,用于提供类型安全的通用缓存。咱们可使用通用的GetCache扩展方法来得到一个ITypedCache:并发
ITypedCache<int, Item> myCache = _cacheManager.GetCache<int, Item>("MyCache");
咱们还可使用AsTyped扩展方法将现有的ICache实例转换为ITypedCache。app
默认的缓存过时时间是60分钟,若是在60分钟以内不使用缓存中的Item,它就会被自动从缓存中删除。咱们能够为全部的缓存配置过时时间,也能够为特定的缓存配置特定时间。异步
//Configuration for all caches Configuration.Caching.ConfigureAll(cache => { cache.DefaultSlidingExpireTime = TimeSpan.FromHours(2); }); //Configuration for a specific cache Configuration.Caching.Configure("MyCache", cache => { cache.DefaultSlidingExpireTime = TimeSpan.FromHours(8); });
上面这段代码将被放到 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是如何工做的
若是须要更复杂的缓存需求,能够扩展EntityCache或建立本身的解决方案。
默认的缓存管理器使用内存缓存。若是有多个并发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="2"/>
不一样的数据库id对于在同一服务器中建立不一样的键空间(隔离缓存)很是有用。
UseRedis方法还有一个重载,它采起一个操做来直接设置选项值(这将覆盖配置文件中的值)。
有关Redis及其配置的更多信息,请参阅Redis文档: Redis documentation
注意:应该安装并运行Redis服务器来使用ABP中的Redis缓存。