ASP.NET Core 2 Identity/EF:如何获取用户类自定义属性并服务端缓存?
当然有可行的方案!你不用每次都写单独的查询方法,通过扩展ASP.NET Identity的机制,结合缓存,就能让await _userManager.GetUserAsync(User)返回包含所有自定义属性的用户对象。下面给你几个实用的实现思路:
方案1:给UserManager写扩展方法,加载关联数据+缓存
你可以封装一个扩展方法,在里面手动Include需要的导航属性,同时加入缓存逻辑,这样每次调用这个方法就能拿到完整且缓存的用户数据:
public static class UserManagerExtensions { public static async Task<ApplicationUser> GetFullUserAsync( this UserManager<ApplicationUser> userManager, ClaimsPrincipal user, IMemoryCache cache) // 注入缓存服务 { var userId = userManager.GetUserId(user); var cacheKey = $"FullUser_{userId}"; // 先尝试从缓存获取 if (cache.TryGetValue(cacheKey, out ApplicationUser cachedUser)) { return cachedUser; } // 缓存未命中,查询数据库并Include导航属性 var fullUser = await userManager.Users .Include(u => u.UserImage) // 如果有其他自定义属性,继续链式Include .SingleOrDefaultAsync(u => u.Id == userId); if (fullUser != null) { // 将用户对象存入缓存,设置30分钟过期时间(可按需调整) cache.Set(cacheKey, fullUser, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30) }); } return fullUser; } }
使用的时候,只要注入IMemoryCache,然后调用:
var currentUser = await _userManager.GetFullUserAsync(User, _cache);
注意:当用户的UserImage或其他属性更新后,记得删除对应缓存键,避免返回旧数据。比如更新后执行_cache.Remove($"FullUser_{userId}")。
方案2:自定义UserStore,自动加载导航属性
UserManager的GetUserAsync最终会调用UserStore的FindByIdAsync方法,所以你可以自定义UserStore,重写这个方法让它自动Include需要的关联数据:
public class CustomUserStore : UserStore<ApplicationUser> { private readonly ApplicationDbContext _dbContext; public CustomUserStore(ApplicationDbContext dbContext, IdentityErrorDescriber describer = null) : base(dbContext, describer) { _dbContext = dbContext; } public override async Task<ApplicationUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default) { // 查询时自动Include UserImage return await _dbContext.ApplicationUsers .Include(u => u.UserImage) .SingleOrDefaultAsync(u => u.Id == userId, cancellationToken); } // 如果需要通过用户名查询也返回完整数据,可以重写FindByNameAsync public override async Task<ApplicationUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken = default) { return await _dbContext.ApplicationUsers .Include(u => u.UserImage) .SingleOrDefaultAsync(u => u.NormalizedUserName == normalizedUserName, cancellationToken); } }
然后在Program.cs里替换默认的UserStore:
builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddUserStore<CustomUserStore>() // 注册自定义UserStore .AddEntityFrameworkStores<ApplicationDbContext>();
这样之后,你原来的await _userManager.GetUserAsync(User)就能直接拿到带UserImage的用户对象了。如果要加缓存,可以在这个自定义UserStore的方法里结合缓存逻辑,或者搭配方案1的缓存思路。
方案3:EF Core二级缓存(可选)
如果想让EF自动缓存查询结果,可以使用EF Core的二级缓存拦截器,这样多次查询同一个用户时,EF会直接从缓存返回,不用每次访问数据库。不过这个是全局的缓存机制,适合减少重复查询的场景。
内容的提问来源于stack exchange,提问作者Eugene
相关产品推荐
相关产品推荐

