学海无涯

导航

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;
        }
    }
}

  

posted on 2022-09-15 18:42  宁静致远.  阅读(624)  评论(0编辑  收藏  举报