zoukankan      html  css  js  c++  java
  • Asp.Net Core 实现查询时缓存修改后缓存过期

    应用场景:

      在高速公路收费系统业务中, 我们的收费站列表信息被频繁各种查询,来自整个自治区的收费站都会查询站信息和其他业务,那么对于站信息查询来说就显得尤其重要, 因此我们设置过期时间为10分钟。 

     //去报using了 下面三个命名空间

    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Caching.Memory;
    namespace Uixe.Blazor.Controllers
    {
        [Authorize]
        [Route("api/[controller]")]
        [ApiController]
        public class PlazasController : ControllerBase
        {
            private readonly ApplicationDbContext _context;
            private readonly ILogger _logger;
            private readonly AppSettings _settings;
            //内存缓存IMemoryCache
            private readonly IMemoryCache _memoryCache;
            //在需要过期的缓存中 AddExpirationToken
            private  CancellationChangeToken _changeToken ;
            //用于修改时调用,以使得_changeToken关联的缓存过期
            private  CancellationTokenSource _cancellationToken;
            
            public PlazasController(ApplicationDbContext context, ILogger<PlazasController> logger, IOptions<AppSettings> option,IMemoryCache memoryCache)
            {
                _context = context;
                _logger = logger;
                _settings = option.Value;
                _memoryCache = memoryCache;
                  //我们需要将CancellationTokenSource本身也缓存在缓存当中
                _cancellationToken = _memoryCache.GetOrCreate("cts" + nameof(PlazasController), a =>
                {
                //没当过期后重新创建CancellationTokenSource
                    _cancellationToken = new CancellationTokenSource();
                   //然后黄建 CancellationChangeToken并关联CancellationTokenSource
                    _changeToken = new CancellationChangeToken(_cancellationToken.Token);
                    //添加至当前缓存元素中以便当_cancellationToken.Canecel()被调用后,本身也能国企
                    a.AddExpirationToken(_changeToken);
                    return _cancellationToken;
                });
            }
      
            [HttpGet(), AllowAnonymous, Authorize(Roles = nameof(UserRole.Anonymous))]
            public async Task<ActionResult<List<Plaza>>> GetPlazas()
            {
                return await _memoryCache.GetOrCreateAsync("_plaza_GetPlazas",  a =>
                {
                //当完整信息或许返回时关联_changeToken
                    a.AddExpirationToken(_changeToken);
                    //设置如果不修改的过期时间 , 因为可能会从数据库或者自动处理程序会修改后台数据。
                    //或者其他程序修改了我们并不知道,所以待有过期时间
                    a.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
                    return    _context.Plazas.ToListAsync();
                });
            }
            /// <summary>
            /// 根据指定的参数<paramref name="args"/>查询收费站信息
            /// </summary>
            /// <param name="args"></param>
            /// <returns></returns>
            [HttpPost("Query"), AllowAnonymous, Authorize(Roles = nameof(UserRole.Anonymous))]
            public async Task<ActionResult<ApiResultPage<List<Plaza>>>> QueryPlazas([FromBody] phc_PlazaQueryArgs args)
            {
              //这是个查询, 我们根据查询条件的对象序列化为json,然后取md5字符串作为key
                if (args == null) args = new phc_PlazaQueryArgs() {  currentPage=1, pageSize=10};
                var key = "_plaza_" + args.GetMd5Sum();
                return await _memoryCache.GetOrCreateAsync(key, async a =>
               {
                   //同样设置过期时间
                   a.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
                    //将_changeToken进行关联
                   a.AddExpirationToken(_changeToken);
                   var query = from p in _context.Plazas select p;
                   if (!string.IsNullOrEmpty(args.plazaid))
                   {
                       query = from q in query where q.Id.Contains(args.plazaid) || q.StationId.StartsWith(args.plazaid) select q;
                   }
                   if (!string.IsNullOrEmpty(args.ipaddress))
                   {
                       query = from q in query where q.IPAddress.StartsWith(args.ipaddress) select q;
                   }
                   if (!string.IsNullOrEmpty(args.plazaname))
                   {
                       query = from q in query where q.StationName.Contains(args.plazaname) select q;
                   }
                   int total  =await  query.CountAsync();
                   var data = await query.Skip(args.pageSize * (args.currentPage - 1)).Take(args.pageSize).OrderBy(q=>q.Id).ToListAsync();
                   return  new  ApiResultPage<List<Plaza>> (ApiCode.OK, "OK", new PageInfo() { Total = total, Current = args.currentPage, PageSize = args.pageSize, TotalPage = (total + args.pageSize - 1) / args.pageSize }, data);
               });
            }
       
            [HttpPut(), Authorize(Roles = nameof(UserRole.Administrator))]
            public async Task<IActionResult> PutPlaza(Plaza plaza)
            {
                _context.Entry(plaza).State = EntityState.Modified;
                try
                {
                    await _context.SaveChangesAsync();
                    //当我们修改并保存后,调用_cancellationToken,它会麦让与之关联所有缓存过期。
                    _cancellationToken.Cancel();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!PlazaExists(plaza.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return NoContent();
            }
         
            [HttpPost, Authorize(Roles = nameof(UserRole.Administrator))]
            public async Task<ActionResult<Plaza>> PostPlaza(Plaza plaza)
            {
                _context.Plazas.Add(plaza);
                await _context.SaveChangesAsync();
                //我们在添加数据时进行取消,
                _cancellationToken.Cancel();
                return CreatedAtAction("GetPlaza", plaza);
            }
        }
       }
    

      

  • 相关阅读:
    C#中的String.Format()方法
    JQuery中的each方法
    [开发笔记]-使用jquery获取url及url参数的方法
    ThinkPHP3.2.3学习笔记3---视图
    PHP命名空间namespace使用小结
    ThinkPHP3.2.3学习笔记2---模型
    PHP中的连贯操作
    关于新技术的学习问题
    ThinkPHP3.2.3学习笔记1---控制器
    WinXP下如何安装及御载MySQL服务
  • 原文地址:https://www.cnblogs.com/MysticBoy/p/12307588.html
Copyright © 2011-2022 走看看