基于C#与ASP.NET Core Identity优化GetUserAsync调用性能
优化ASP.NET Core Identity获取当前用户ID的性能方案
从性能角度出发,你可以通过以下几种方式避免重复调用数据库查询当前用户:
1. 直接从Claims提取用户ID
ASP.NET Core Identity默认会将用户ID存入ClaimTypes.NameIdentifier类型的Claim中,完全不需要访问数据库就能直接获取:
private string GetCurrentUserId() { return HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); }
这是性能最优的方案,因为Claim信息已经包含在请求的身份凭证里,没有任何数据库开销。
2. 请求周期内缓存用户信息
如果除了ID还需要用户的其他少量字段,可以在单个请求开始时查询一次用户数据,然后缓存到HttpContext.Items中,整个请求生命周期内复用:
第一步:实现请求过滤器
public class CurrentUserCacheFilter : IAsyncActionFilter { private readonly UserManager<ApplicationUser> _userManager; public CurrentUserCacheFilter(UserManager<ApplicationUser> userManager) { _userManager = userManager; } public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var httpContext = context.HttpContext; if (httpContext.User.Identity.IsAuthenticated) { var user = await _userManager.GetUserAsync(httpContext.User); // 按需缓存ID或完整用户对象 httpContext.Items["CurrentUserId"] = user.Id; // httpContext.Items["CurrentUser"] = user; } await next(); } }
第二步:注册过滤器
在Program.cs中添加过滤器配置:
builder.Services.AddControllersWithViews(options => { options.Filters.Add<CurrentUserCacheFilter>(); });
第三步:控制器内复用缓存
string currentUserId = HttpContext.Items["CurrentUserId"] as string;
这样整个请求过程中只会执行一次数据库查询,后续操作直接读取缓存。
3. 自定义Claims扩展常用字段
如果需要的用户字段不止ID(比如昵称、角色),可以在登录时将这些字段添加到Claims中,之后直接从Claims读取,彻底避免数据库查询:
第一步:自定义Claims生成器
public class CustomUserClaimsFactory : UserClaimsPrincipalFactory<ApplicationUser> { public CustomUserClaimsFactory(UserManager<ApplicationUser> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor) { } protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user) { var identity = await base.GenerateClaimsAsync(user); // 添加需要的自定义字段 identity.AddClaim(new Claim("NickName", user.NickName)); identity.AddClaim(new Claim("Role", user.Role)); return identity; } }
第二步:注册自定义Factory
builder.Services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomUserClaimsFactory>();
第三步:直接读取Claims
string nickName = HttpContext.User.FindFirstValue("NickName");
注意:这种方式适合不常变动的用户字段,如果用户信息更新,需要重新登录才能同步Claims数据。
内容的提问来源于stack exchange,提问作者Goober
相关产品推荐
相关产品推荐

