You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET MVC 首页节假日校验频繁查询数据库优化咨询

ASP.NET MVC 节假日判断缓存优化方案

方案选择说明

节假日判断是全局公共规则,和单个用户无关,不建议使用Session实现:Session属于用户会话级存储,会导致每个用户都单独存储一份判断结果,额外占用资源,性价比极低,优先选择全局缓存方案。

方案1:单服务器部署用内置内存缓存(最常用)

  • 第一步:注册缓存服务
    在Program.cs(.NET 6+)或者Startup.cs的ConfigureServices方法中添加服务注册:
// .NET 6+ Program.cs示例
builder.Services.AddMemoryCache();
  • 第二步:在控制器中注入缓存服务
    修改CustomersController的构造函数,注入IMemoryCache实例:
private readonly YourDbContext _context;
private readonly IMemoryCache _memoryCache;

public CustomersController(YourDbContext context, IMemoryCache memoryCache)
{
    _context = context;
    _memoryCache = memoryCache;
}
  • 第三步:修改Index方法的判断逻辑
    替换原有数据库查询逻辑,优先走缓存,缓存失效后才查数据库,缓存过期时间设置为美东时间当日午夜,自动更新次日的判断结果:
public async Task<IActionResult> Index(string sortOrder, string searchString,
                                       int? pageNumber, string currentFilter)
{
    var timeUtc = DateTime.UtcNow;
    var easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
    var todayDt = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, easternZone);
    // 按美东时间日期生成缓存key,确保每天的结果单独缓存
    var cacheKey = $"IsHoliday_{todayDt:yyyyMMdd}";

    // 缓存中不存在数据时才查询数据库
    if (!_memoryCache.TryGetValue(cacheKey, out bool isHoliday))
    {
        // 用Any替代Count,只要判断存在即可,数据库查询效率更高
        isHoliday = _context.HolidayWeeks.Any(hc => hc.HolidateDate.Date == todayDt.Date);
        // 设置缓存过期时间为美东时间当日午夜,到期自动失效
        var expireTime = new DateTimeOffset(todayDt.Date.AddDays(1), easternZone.BaseUtcOffset);
        _memoryCache.Set(cacheKey, isHoliday, expireTime);
    }

    if (isHoliday)
    {
        return View("/Views/Customers/AppNotAvailable.cshtml");
    }

    // 原有客户页面业务逻辑
    // ...
}

方案2:多服务器分布式部署用分布式缓存

如果你的应用是多实例部署,为了避免每个实例都单独查询数据库,可以使用ASP.NET Core提供的IDistributedCache分布式缓存,底层可以对接Redis、SQL Server等公共存储,逻辑和内存缓存基本一致,只是接口调用方式略有差异,缓存数据全局共享,所有实例共用同一份判断结果。

进阶优化:全局拦截统一处理

如果后续有多个页面都需要做节假日拦截,建议把判断逻辑封装为Action过滤器或者中间件,不用在每个Action中重复编写代码:

  1. 自定义节假日校验过滤器:
public class HolidayCheckFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        var cache = context.HttpContext.RequestServices.GetRequiredService<IMemoryCache>();
        var dbContext = context.HttpContext.RequestServices.GetRequiredService<YourDbContext>();
        
        // 复用上述节假日判断逻辑
        var timeUtc = DateTime.UtcNow;
        var easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
        var todayDt = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, easternZone);
        var cacheKey = $"IsHoliday_{todayDt:yyyyMMdd}";

        if (!cache.TryGetValue(cacheKey, out bool isHoliday))
        {
            isHoliday = dbContext.HolidayWeeks.Any(hc => hc.HolidateDate.Date == todayDt.Date);
            var expireTime = new DateTimeOffset(todayDt.Date.AddDays(1), easternZone.BaseUtcOffset);
            cache.Set(cacheKey, isHoliday, expireTime);
        }

        if (isHoliday)
        {
            context.Result = new ViewResult
            {
                ViewName = "/Views/Customers/AppNotAvailable.cshtml"
            };
        }
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // 无需实现
    }
}
  1. 注册过滤器,可以选择全局注册对所有请求生效,或者只给需要拦截的Controller/Action打标记使用。

内容的提问来源于stack exchange,提问作者user4912134

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 12:06:02