IMemoryCache内存缓存
对于ASP.NET Core MVC 项目,框架会自动注入内存缓存服务。对于 ASP.NET Web API 等需要手动注入内存缓存服务。
注入内存缓存服务:
builder.Services.AddMemoryCache();//注入内存缓存服务
内存缓存工具类接口:
using Microsoft.AspNetCore.Routing.Template;
using Microsoft.Extensions.Caching.Memory;
namespace TestWebApplication.Utility
{
public interface IMemoryCacheHelper
{
TResult? GetOrCreate<TResult>(string cacheKey, Func<ICacheEntry, TResult?>
valueFactory, int expireSeconds = 60);
/// <summary>
/// 从内存缓存中获取数据,没有则通过委托方法从数据库中获取并设置缓存
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="cacheKey">键</param>
/// <param name="valueFactory">当缓存中不存在时,用此委托从数据库中获取</param>
/// <param name="expireSeconds">多少秒后过期</param>
/// <returns></returns>
Task<TResult?> GetOrCreateAsync<TResult>(string cacheKey, Func<ICacheEntry, Task<TResult?>>
valueFactory, int expireSeconds = 60);
void Remove(string cacheKey);
}
}
实现:
using Microsoft.Extensions.Caching.Memory;
namespace TestWebApplication.Utility
{
public class MemoryCacheHelper : IMemoryCacheHelper
{
private readonly IMemoryCache _cache;
public MemoryCacheHelper(IMemoryCache cache)
{
_cache = cache;
}
private static void ValidateValueType<TResult>()
{
Type typeResult = typeof(TResult);
if (typeResult.IsGenericType)//如果是泛型类型,获取泛型类型的定义
{
typeResult = typeResult.GetGenericTypeDefinition();
}
if (typeResult == typeof(IEnumerable<>) || typeResult == typeof(IEnumerable<TResult>)
|| typeResult == typeof(IAsyncEnumerable<TResult>)
|| typeResult == typeof(IQueryable<TResult>)
|| typeResult == typeof(IQueryable))
{
throw new InvalidOperationException($"please use List<T> or T[] instead.");
}
}
private static void InitCacheEntry(ICacheEntry entry, int baseExpireSeconds)
{
double sec = Random.Shared.Next(baseExpireSeconds, baseExpireSeconds * 2);
TimeSpan expiration = TimeSpan.FromSeconds(sec);
entry.AbsoluteExpirationRelativeToNow = expiration;
}
public TResult? GetOrCreate<TResult>(string cacheKey, Func<ICacheEntry, TResult?> valueFactory, int expireSeconds = 60)
{
throw new NotImplementedException();
}
public async Task<TResult?> GetOrCreateAsync<TResult>(string cacheKey, Func<ICacheEntry, Task<TResult?>> valueFactory, int expireSeconds = 60)
{
ValidateValueType<TResult>();
if (_cache.TryGetValue(cacheKey, out TResult? result)==false)
{
using ICacheEntry entry = _cache.CreateEntry(cacheKey);
InitCacheEntry(entry, expireSeconds);
result = await valueFactory(entry);
entry.Value = result;
}
return result;
}
public void Remove(string cacheKey)
{
_cache.Remove(cacheKey);
}
}
}
客户端使用
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using TestWebApplication.Utility;
namespace TestWebApplication
{
[Route("api/[controller]")]
[ApiController]
public class ValuesMemoryController : ControllerBase
{
private readonly ILogger<ValuesMemoryController> _logger;
private readonly ApplicationDbContext _context;
private readonly IMemoryCache _memoryCache;
private readonly IMemoryCacheHelper _CacheHelper;
public ValuesMemoryController(ILogger<ValuesMemoryController> logger, ApplicationDbContext context, IMemoryCache memoryCache, IMemoryCacheHelper cacheHelper)
{
_logger = logger;
_context = context;
_memoryCache = memoryCache;
_CacheHelper = cacheHelper;
}
[HttpGet]
public async Task<IEnumerable<PO>> GetPOs()
{
_logger.LogInformation($"开始执行{nameof(GetPOs)}:{DateTime.Now}");
//var items = await _memoryCache.GetOrCreateAsync("AllPO", async (e) =>
//{
// e.SlidingExpiration=TimeSpan.FromSeconds(10);
// e.AbsoluteExpirationRelativeToNow=TimeSpan.FromSeconds(30);
// _logger.LogInformation("从数据库中读取数据");
// return await _context.PO.Take(10).ToListAsync();
//});
var items = await _CacheHelper.GetOrCreateAsync("AllPO2", async (e) =>
{
_logger.LogInformation("从数据库中读取数据");
return await _context.PO.Take(10).ToListAsync();
}, 10);
_logger.LogInformation("把数据返回给调用者");
return items;
}
}
}
浙公网安备 33010602011771号