缓存

介绍

  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的缓存。缓存名称是大小写敏感的,意味着“MyCache”和“MYCACHE”是不同的缓存。

  警告:GetCache方法

  不要在构造函数中使用GetCache。如果类不是单例的话,缓存可能会被释放。

ICache

  ICacheManager.GetCaChe方法返回ICache。缓存是单例的(每个缓存名称)。首次需要的时候创建,然后每次都返回同样的缓存对象。所以,我们可以在不同的类(客户端)使用相同的名字共享同样的缓存。

  在实例代码中,我们看到了ICache.Get方法的简单使用。它有两个参数:

  • Key:缓存中一个项的唯一字符串键。
  • factory:如果指定的键没有项目时调用。工厂方法应该创建并返回真实的项。如果指定的键在缓存中存在的话就不会调用这个方法。

  ICache接口也有如GetOrDefault,Set,Remove和Clear这样的方法。同样也有这些方法的异步版本。

ITypedCache

ICache接口使用string类型作为键,object作为值。ITypeCache是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();
}); //Configuration for a specific cache
Configuration.Caching.Configure("MyCache", cache =>
{
cache.DefaultSlidingExpireTime = TimeSpan.FromHours();
});

  这段代码需要放在模块的PreInitialize方法中。使用这段代码,MyCache将在8个小时后过期,其他缓存将在2小时后过期。

  配置动作在缓存第一建立(首次请求)时调用。配置并不仅限于DefaultSlidingExpireTime,因为缓存对象为ICache,可以使用它的属性和方法自由配置和初始化。

实体缓存

  虽然ABP缓存系统是通用的,如果想缓存实体,可以使用EntityCache基类。如果我们通过Ids获取到实体并且想通过Id缓存实体而不是经常从数据库查询,我们就可以使用这个基类。假如我们有一个Person实体,如下:

public class Person : Entity
{
public string Name { get; set; } public int Age { get; set; }
}

  假如我们知道Id并想以此获取people的Name。首先,我们创建一个类储存缓存项:

[AutoMapFrom(typeof(Person))]
public class PersonCacheItem
{
public string Name { get; set; }
}

  不应该直接在缓存中直接存储实体,因为缓存可能需要序列化缓存的对象,实体可能不能被序列化(尤其是有导航属性时)。这就是我们在缓存中定义一个简单类(像DTO)存储数据的原因。因为我们想使用AutoMapper自动将Person实体转换为PersonCahcedItem,所以在类上添加了AutoMapFrom特性。如果我们不使用AutoMapper,那需要重写EntityCache类的MapToCacheItem方法来实现自动转换或映射。

  我们希望定义一个缓存类的接口,虽然这不是必须的:

public interface IPersonCache : IEntityCache<PersonCacheItem>
{ }

最后,我们可以创建缓存类缓存Person实体了:

public class PersonCache : EntityCache<Person, PersonCacheItem>, IPersonCache, ITransientDependency
{
public PersonCache(ICacheManager cacheManager, IRepository<Person> repository)
: base(cacheManager, repository)
{ }
}

  就这样,我们的person缓存可以使用了。Cache类可以是临时的(如本例)也可以是单例的。这并不意味着缓存数据是临时的。在应用中,它总是全局缓存并且访问是线程安全的。

  现在,不管何时我们需要person的Name时,我们可以通过person`s 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属性。

实体缓存如何工作

  • 在首次调用时,从仓储(从数据库)获取实体。然后在之后的调用从缓存获取。
  • 如果实体被更新或删除,会自动使缓存实体无效。然后,在下次调用时会从数据库中重新获取。
  • 使用IObjectMapper映射实体和缓存项。IObjectMapper通过AutoMapper模块实现。所以,如果使用的话需要AutoMapper模块。可以重写MapToCacheItem方法手动映射实体和缓存项。
  • 使用缓存类FullName作为缓存名称。可以通过向基类构造函数传递缓存名称来改变它。
  • 线程安全。

  如果需要更复杂的缓存,可以扩展EntityCache或创建自己的解决方案。

Redis缓存集成

  默认的缓存管理器使用内存缓存。所以,如果有多于一个并发网络服务器运行同样的应用,将会成为一个问题。在这种情况下,需要使用一个分布式/中央缓存服务器。可以很简单的使用Redis作为缓存服务器。

  首先,需要在应用(例如,可以安装在Web工程)中安装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=""/>

  在同一个服务器中,不同的数据库ids用来创建不同的关键空间(隔离缓存)。

  UseRedis方法有个重载,可以用来直接设置选项值(在配置文件中重写值)。

  参见Redis文档获取关于Redis及配置的更多信息。

  注意:Redis服务器应该安装并运行,以便在ABP中使用Redis缓存。

返回主目录

ABP官方文档翻译 2.3 缓存的更多相关文章

  1. ABP官方文档翻译 10.1 ABP Nuget包

    ABP Nuget包 Packages Abp Abp.AspNetCore Abp.Web.Common Abp.Web Abp.Web.Mvc Abp.Web.Api Abp.Web.Api.OD ...

  2. 0.0 ABP官方文档翻译目录

    一直想学习ABP,但囿于工作比较忙,没有合适的契机,当然最重要的还是自己懒.不知不觉从毕业到参加工作七年了,没留下点儿什么,总感觉很遗憾,所以今天终于卯足劲鼓起勇气开始写博客.有些事能做的很好,但要跟 ...

  3. ABP官方文档翻译 2.5 设置管理

    设置管理 介绍 关于 ISettingStore 定义设置 设置范围 重写设置定义 获取设置值 服务端 客户端 更改设置 关于缓存 介绍 每个应用都需要存储设置,并且在应用的某些地方需要使用这些设置. ...

  4. ABP官方文档翻译 6.2.1 ASP.NET Core集成

    ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Acti ...

  5. ABP官方文档翻译 5.1 Web API控制器

    ASP.NET Web API控制器 介绍 AbpApiController基类 本地化 其他 过滤器 审计日志 授权 反伪造过滤器 工作单元 结果包装和异常处理 结果缓存 校验 模型绑定器 介绍 A ...

  6. ABP官方文档翻译 0.0 ABP官方文档翻译目录

    一直想学习ABP,但囿于工作比较忙,没有合适的契机,当然最重要的还是自己懒.不知不觉从毕业到参加工作七年了,没留下点儿什么,总感觉很遗憾,所以今天终于卯足劲鼓起勇气开始写博客.有些事能做的很好,但要跟 ...

  7. ABP官方文档翻译 1.5 多租户

    多租户 什么是多租户? 数据库和部署架构 多部署-多数据库 单部署-多数据库 单部署-单数据库 单部署-混合数据库 多部署-单/多/混合数据库 ABP的多租户 启用多租户 租主和租户 会话 决定当前租 ...

  8. ABP官方文档翻译 9.3 NHibernate集成

    NHibernate集成 Nuget包 配置 实体映射 仓储 默认实现 自定义仓储 应用程序特定基础仓储类 ABP可以使用任何ORM框架,它内置集成NHibernate.此文档将讲解ABP如何使用NH ...

  9. ABP官方文档翻译 9.2 Entity Framework Core

    Entity Framework Core 介绍 DbContext 配置 在Startup类中 在模块PreInitialize方法中 仓储 默认仓储 自定义仓储 应用程序特定基础仓储类 自定义仓储 ...

随机推荐

  1. 51Nod 1046 A^B Mod C(日常复习快速幂)

    1046 A^B Mod C 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 给出3个正整数A B C,求A^B Mod C. 例如,3 5 8,3^5 Mod 8 = ...

  2. 2017西安网络赛 F

    f(cos(x))=cos(n∗x) holds for all xx. Given two integers nn and mm, you need to calculate the coeffic ...

  3. Wolf and Rabbit

    http://acm.hdu.edu.cn/showproblem.php?pid=1222 Wolf and Rabbit Time Limit: 2000/1000 MS (Java/Others ...

  4. 一 : springmvc常用注解

    springmvc常用注解详解1.@Controller在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层 ...

  5. tinyxml的封装与使用(转载)

    tinyxml是个高效精简的xml解析开源代码. 针对tinyxml直接使用对于对xml不是很熟悉的入门新手来说,有些概念难以理解,因此我将其封装后,供大家使用. 头文件: #include &quo ...

  6. 微信小程序使用字体图标的方法

    一.先到阿里巴巴矢量图标库(http://iconfont.cn/),用微博帐号登录,搜索你想要的图标,然后添加入库 从项目里下载下来并解压,找到ttf格式文件 二.到这个平台https://tran ...

  7. light oj 1184 Marriage Media

    题目: You run a marriage media. You take some profiles for men and women, and your task is to arrange ...

  8. parsing XML document from class path resource [config/applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [config/applicationContext.xml] 解决方案

    parsing XML document from class path resource [config/applicationContext.xml]; nested exception is j ...

  9. MLlib--决策树

    转载请标明出处http://www.cnblogs.com/haozhengfei/p/d65ab6ccff684db729f44a947ac9e7da.html 决策树 1.什么是决策树    决策 ...

  10. Sqoop介绍

    Sqoop介绍 http://sqoop.apache.org http://sqoop.apache.org/docs/1.4.6/SqoopUserGuide.html   1.什么是Sqoop? ...