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緩存。