0

Asp.Net Core 实现查询时缓存修改后缓存过期

苦寒行 2020-02-15
10
摘要:用朋友文章活跃一下

应用场景:

  在高速公路收费系统业务中, 我们的收费站列表信息被频繁各种查询,来自整个自治区的收费站都会查询站信息和其他业务,那么对于站信息查询来说就显得尤其重要, 因此我们设置过期时间为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);
            }
    }
       }



    「喜欢文章,快来给作者赞赏墨值吧」

    评论

    0
    0
    墨值排行
    今日本周综合
    近期活动
    全部
    相关课程
    全部