簡介 ABP提供了一個緩存介面,它內部使用了這個緩存介面。雖然介面的預設實現是MemoryCache,但可以用任何其它實現的緩存供應器。Abp.RedisCache包用Redis實現了緩存(查看下方的“Redis 緩存集成”)。 ICacheManager 緩存的主要介面是ICacheManager ...
簡介
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的緩存。
警告:GetCache方法
如果你的類不是單例,不要在你構造器里使用GetCache,否則可能會銷毀你的緩存。
ICache
ICacheManager.GetCache方法返回一個ICache。一個緩存是單例的(每個緩存名)。第一次請求時創建,然後一直返回同一個緩存對象。所以,我們可以在不同的類(客戶端)里用相同的名字共用同一個緩存。
在示例代碼里,我們看到了ICache.get方法的簡單使用。它有兩個參數:
key:字元串,必需,一個緩存項的鍵。
factory:一個action(行為),在找不到指定key的緩存項時調用,Factory方法應該創建並返回切實的項,如果指定key的緩存已存在,就不調用。
ICache介面也有如GetOrDefault、Set、Remove和Clear等方法。同樣也有async版本。
ITypedCache
ICache介面以字元串為key,值是object類型。ITypedCache包裝了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(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獲取的實體,我們可以用這個基類緩存它們,就不用再頻繁地從資料庫查詢。假設我們有如下所示的一個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特性,它可以自動地把Person轉換成PersonCacheItem對象。如果我們不使用AutoMapFrom,我們應該為重載EntityCache類的MapToCacheItem方法,手動轉換/映射。
雖然不是必需,但我們可能想為我們的緩存類定義一個介面:
public interface IPersonCache : IEntityCache<PersonCacheItem> { }
最後,我們可以為實體創建緩存類:
public class PersonCache : EntityCache<Person, PersonCacheItem>, IPersonCache, ITransientDependency { public PersonCache(ICacheManager cacheManager, IRepository<Person> repository) : base(cacheManager, repository) { } }
這就是全部代碼,我們的Person緩存已經可用。緩存類可以是暫時的(如示例)或單體的,這不是說緩存的數據是暫時的,它始終在你的應用里是全局的並線程安全的。
現在,任何需要Person的Name時,我們可以通過person的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屬性。
EntityCache 是如何工作
- 在第一個調用里獲取從倉儲(從資料庫)獲取實體,然後在接下來的調用里從緩存里獲取。
- 如果實體更新或刪除後,它自動使緩存失效,所以它將在下一個調用里重新從資料庫獲取。
- 使用IObjectMapper映射到緩存項,AutoMpper模塊實現了IObjectMapper,所以需要AutoMapper模塊。你可以重載MapToCacheItem方法,手動映射實體到緩存項。
- 使用緩存類全名作為緩存時的名稱,你可以通過傳遞一個緩存名給基構造器來改變它。
- 是線程安全的。
如果你需要更複雜的緩存技術,你可以擴展EntityCache或創建你自己的解決方案。
Redis 緩存集成
預設緩存管理使用的是記憶體緩存。所以,如果你有多個併發的Web伺服器使用同個應用,可能會成為一個問題,在這種情況下,你需要一個分佈/集中緩存服務,你就可以簡單的使用Redis做為你的緩存伺服器。
首先,你要在你的應用里,安裝Abp.RedisCache的Nuget包(例如,你可在你的Web項目里安裝)。接著為AbpRedisCacheModule添加DependsOn特性,然後在你模塊預初始化方法里調用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方法也有一個重載,用給定的action(行為)直接設置選項值(在配置文件中重寫)。
查看更多有關Redis信息及它的配置,請查閱Redis文檔。
提醒:Redis伺服器應該安裝和運行在ABP里。