官方文档地址:https://aspnetboilerplate.com/Pages/Documents/Caching
1.先set 后取出
需要在控制器中注入ICacheManager,
[Route("api/[controller]/[action]")]
[ApiController]
public class WeChatController : TestControllerBase
{
private readonly ICacheManager _cacheManager;
private IHttpClientFactory _httpClient;
public WeChatController( IHttpClientFactory httpClient, ICacheManager cacheManager)
{
this._cacheManager = cacheManager;
this._httpClient = httpClient;
}
/// <summary>
/// 获取微信ID
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<dynamic> GetWechatID(string js_code)
{
try
{
using (var client = _httpClient.CreateClient())
{
var url = $"https://api.weixin.qq.com/sns/jscode2session?appid=111&secret=11&js_code={js_code}&grant_type=authorization_code";
//使用注入的httpclientfactory获取client
client.BaseAddress = new Uri(url);
//设置请求体中的内容,并以post的方式请求
var response = await client.GetAsync(url);
//获取请求到数据,并转化为字符串
var result = response.Content.ReadAsStringAsync().Result;
dynamic aa = JsonConvert.DeserializeObject<dynamic>(result);
string session_key = aa.session_key;
string openid = aa.openid;
string bb = PublicMethods.Encrypt(openid);
_cacheManager.GetCache("微信登录").Remove(bb);//先删除之前缓存的数据
_cacheManager.GetCache("微信登录").Set(bb, session_key);//可以理解为定义一个表 然后写入数据 以bb为标识 session_key是要保存的数据
return Json(new { ok = true, msg = "sucess", data = bb });
}
}
catch (Exception e)
{
return Json(new { ok = false, msg = "error", data = e.Message });
}
}
/// <summary>
/// 微信步数解密
/// </summary>
/// <returns></returns>
[HttpPost]
public ActionResult Decrypt(T微信步数解密 Decrypt)
{
string sessionKey = _cacheManager.GetCache("微信登录").GetOrDefault(Decrypt.wechatid).ToString(); //取出缓存的sessionKey
return Ok(sessionKey);
}
}
2.先get没有则存入数据
[Route("api/[controller]/[action]")]
[ApiController]
public class TablesController : TestControllerBase
{
private readonly ICacheManager _cacheManager;
private string currentUserName;
public TablesController(ICacheManager cacheManager)
{
_cacheManager = cacheManager;
}
[NonAction]
private T医生 Get责任医生By卫生室编号InCache(string _卫生室编号)
{
return _cacheManager
.GetCache("责任医生")
.Get(_卫生室编号, () => Get责任医生By卫生室编号(_卫生室编号)) as T医生;
}
[NonAction]
private T医生 Get责任医生By卫生室编号(string _卫生室编号)
{
using (IDbConnection dbConnection = DapperHelper.CreateLocalConnection())
{
var sql责任医生 = $@"select top 1 *
from 表_医生 where
医生类别='责任医生' and 组织机构编号='{_卫生室编号}'";
return dbConnection.QueryFirstOrDefault<T医生>(sql责任医生);
}
}
}
3.设置缓存失效时间
默认缓存超时是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个小时。 ***.core——***CoreModule——PreInitialize()
在第一次创建缓存(在第一次请求)调用你的配置行为。配置不是只有DefaultSlidingExpireTime,由于缓存对象是一个ICache,所以你可以用它的属性和方法,自由的配置和初始化。
4.实体缓存
虽然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属性。
- 在第一个调用里获取从仓储(从数据库)获取实体,然后在接下来的调用里从缓存里获取。
- 如果实体更新或删除后,它自动使缓存失效,所以它将在下一个调用里重新从数据库获取。
- 使用IObjectMapper映射到缓存项,AutoMpper模块实现了IObjectMapper,所以需要AutoMapper模块。你可以重载MapToCacheItem方法,手动映射实体到缓存项。
- 使用缓存类全名作为缓存时的名称,你可以通过传递一个缓存名给基构造器来改变它。
- 是线程安全的。
如果你需要更复杂的缓存技术,你可以扩展EntityCache或创建你自己的解决方案。
默认缓存管理使用的是内存缓存。所以,如果你有多个并发的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里。