## 简介
缓存的概念，相信大家都很了解了。主要目的是为了提高系统运行效率，减少服务器压力。由于硬盘的访问速度远远小于内存的速度，

- 对于需要频繁访问的数据，我们可以使用缓存。
- 对于需要时间过期功能的数据，我们可以使用缓存。

> 缓存中尽量不要存放重要数据，它和硬盘的区别在于，强制中断之后，缓存的数据将会被清空难以找回。


框架的缓存模块是基于面向对象的。如果接触过其他缓存框架，可能在第一次接触框架的这种方式，会有一定的不适应，但是对于复杂类型、复杂key的情况，面向对象化的方式，边界会更加清晰。
## 使用方式
使用 `IDistributedCache`进行管理缓存，包括
- 缓存读取
- 缓存覆盖
- 缓存删除
- 缓存写入

支持时间过期及批量操作

### IDistributedCache<TCacheItem>简单类型
如果你的缓存的key只是一个固定的字符串，那么直接可以通过依赖注入进行`IDistributedCache<TCacheItem>`接口即可，TCacheItem就是你定义存储下来的缓存对象
例如：
``` cs
//定义存储模型
 public class BookCacheItem
    {
        public string Name { get; set; }

        public float Price { get; set; }
    }

//进行获取或者添加
  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(), //缓存键
                async () => await GetBookFromDatabaseAsync(bookId),
                () => new DistributedCacheEntryOptions
                {
                    AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
                }
            );
        }

        private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
        {
            //TODO: 从数据库获取数据
        }
    }

```

### IDistributedCache<TCacheItem, TCacheKey>简单key
同时，推荐使用`IDistributedCache<TCacheItem, TCacheKey>`接口，把key和value同时都当作对象去标识，更加符合面向对象的特征

这里TCacheKey可以为简单类型Guid

``` cs

[CacheName("Books")]
    public class BookCacheItem
    {
        public string Name { get; set; }

        public float Price { get; set; }
    }


    public class BookService : ITransientDependency
    {
        private readonly IDistributedCache<BookCacheItem, Guid> _cache;

        public BookService(IDistributedCache<BookCacheItem, Guid> cache)
        {
            _cache = cache;
        }

        public async Task<BookCacheItem> GetAsync(Guid bookId)
        {
            return await _cache.GetOrAddAsync(
                bookId, //Guid类型作为缓存键
                async () => await GetBookFromDatabaseAsync(bookId),
                () => new DistributedCacheEntryOptions
                {
                    AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
                }
            );
        }
        private Task<BookCacheItem> GetBookFromDatabaseAsync(Guid bookId)
        {
            //TODO: 从数据库获取数据
        }
    }

```

### 复杂类型的缓存键
如果TCacheKey为复杂类型，可以重写key的ToString方法即可
``` cs
public class UserInOrganizationCacheKey
{
    public Guid UserId { get; set; }
 
    public Guid OrganizationId { get; set; }

    //构建缓存key
    public override string ToString()
    {
        return $"{UserId}_{OrganizationId}";
    }
}

public class BookService : ITransientDependency
{
    private readonly IDistributedCache<UserCacheItem, UserInOrganizationCacheKey> _cache;

    public BookService(
        IDistributedCache<UserCacheItem, UserInOrganizationCacheKey> cache)
    {
        _cache = cache;
    }
    
    ...
}
```

## 配置
AbpDistributedCacheOptions 是配置缓存的主要Option类.

示例：为应用程序设置缓存键前缀

``` cs
Configure<AbpDistributedCacheOptions>(options =>
{
    options.KeyPrefix = "MyApp1";
});

```

## 其他缓存实现
默认使用的缓存实现是基于`MemoryCache`本地缓存实现的

同时还支持其他的实现：
[Redis支持](https://docs.abp.io/zh-Hans/abp/latest/Redis-Cache)

由于模块化，只需要在对应的模块中添加依赖即可，不需要修改任何其他代码。

