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

ASP.NET Core中如何缓存按用户角色区分的导航栏链接?

问题根因

你原来的<cache>标签写法确实没有解决数据库查询开销的问题:因为获取用户姓名、角色的查询逻辑写在了缓存标签的外层,哪怕缓存命中,这部分数据库查询还是会每次请求都执行。

可行优化方案

方案1:优先使用Claims存储用户基础信息(推荐,无需额外缓存)

这是成本最低、效果最好的方案,可避免所有相关数据库查询:

  1. 在用户登录逻辑中,把用户姓名、角色直接写入ClaimsIdentity:
// 登录时添加自定义Claims示例
var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, user.FirstName + " " + user.LastName),
    new Claim(ClaimTypes.Role, roleName)
};
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));

如果你用的是ASP.NET Core Identity自带的登录逻辑,可以实现IUserClaimsPrincipalFactory<AppUser>接口自定义Claims发放,不需要修改原有登录流程。
2. 局部视图里直接从User对象读取信息,完全不需要查数据库:

@inject SignInManager<AppUser> SignInManager

@if (SignInManager.IsSignedIn(User))
{
    // 直接从Claims读取,无数据库开销
    string name = User.Identity.Name;
    string role = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value;
    
    // 后续渲染逻辑不变
}

方案2:用IMemoryCache缓存用户信息

如果不想修改Claims逻辑,用内存缓存也完全能满足需求,你没有分布式缓存的场景下足够使用:

  1. 在_LoginPartial.cshtml中注入IMemoryCache
  2. 以用户ID为缓存键,缓存用户姓名和角色,设置合理的过期时间(比如15分钟滑动过期):
@inject IMemoryCache _memoryCache
@inject SignInManager<AppUser> SignInManager
@inject UserManager<AppUser> UserManager

@if (SignInManager.IsSignedIn(User))
{
    string userId = UserManager.GetUserId(User);
    // 从缓存读,没有则查询数据库并存入缓存
    var (name, role) = await _memoryCache.GetOrCreateAsync($"UserInfo_{userId}", async entry =>
    {
        entry.SlidingExpiration = TimeSpan.FromMinutes(15);
        // 合并为一次数据库查询,减少往返
        var userData = await UserManager.Users
            .Where(u => u.Id == userId)
            .Select(u => new 
            {
                FullName = u.AppUser.FirstName + " " + u.AppUser.LastName,
                u
            })
            .FirstOrDefaultAsync();
        string role = (await UserManager.GetRolesAsync(userData.u)).FirstOrDefault();
        return (userData.FullName, role);
    });
    
    // 后续渲染逻辑
}

注意:当用户修改个人信息、变更角色时,需要主动删除对应用户ID的缓存,避免展示旧数据。

导航栏链接的缓存优化

因为同角色的导航链接是完全一致的,这部分可以单独按角色缓存,进一步减少渲染开销:

<!-- 姓名单独渲染,不参与缓存 -->
<span class="user-name">@name</span>
<!-- 链接部分按角色缓存,所有同角色用户共用一份缓存 -->
<cache vary-by="@role">
    <ul class="navbar-nav mr-auto mt-2 mt-lg-0 d-lg-flex justify-content-center flex-fill ">
        <li class="nav-item ">
            <a class="nav-link text-dark text-uppercase font-size-xlarge font-weight-light" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
        </li>
        @switch (role)
        {
            case "Student": 
                <li class="nav-item">
                   <a class="nav-link" asp-area="Exams" asp-controller="Schedules" asp-action="Index">Exams</a>
                </li>
                break;
            case "Instructor":
                <li class="nav-item">
                   <a class="nav-link" asp-area="Programs" asp-controller="Programs" asp-action="Index">Programs</a>
               </li> 
                break;
            case "Administrator":
                break;
        }
    </ul>
</cache>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 10:54:02