I'm writing a class that will be available as a service, which provides some information about the current user.
public class UserContextService
{
private readonly ApplicationDbContext DbContext;
private readonly IHttpContextAccessor ContextAccessor;
private readonly UserManager<ApplicationUser> UserManager;
public UserContextService(ApplicationDbContext dbContext, UserManager<ApplicationUser> userManager, IHttpContextAccessor contextAccessor)
{
DbContext = dbContext;
UserManager = userManager;
ContextAccessor = contextAccessor;
}
public async Task<UserContextModel> GetUserContext()
{
if (UserContextModel == null)
{
ClaimsPrincipal? principal = ContextAccessor.HttpContext?.User;
if (principal == null)
throw new InvalidOperationException("No ClaimsPrincipal found for user.");
ApplicationUser user = await UserManager.GetUserAsync(principal);
UserContextModel = await DbContext.Facilities
.Where(f => f.Id == user.FacilityId)
.Select(f => new UserContextModel
{
Name = user.Name,
FacilityId = f.Id,
FacilityName = f.Name,
})
.FirstOrDefaultAsync();
}
Debug.Assert(UserContextModel != null);
return UserContextModel;
}
private UserContextModel? UserContextModel = null;
}
This works well. But it may be called for nearly all pages so I want to make it as efficient as possible.
Is there any way to optimize GetUserContext()? In particular, I'm using UserManager.GetUserAsync() to get the user, and then I'm doing a query to get information about the facility. That could easily be combined into a single query with a join. And that seems like it would be more efficient.
But I would need the user ID to make that single query. And I don't see another way to obtain the ID of the current user without retrieving the current ApplicationUser record.
Any tips for optimizing this?