问题
Currently have ApplicationUser
class with some custom properties, like:
public class ApplicationUser : IdentityUser
{
public string Name { get; set; }
public List<Content> Content { get; set; }
}
I'd like to get the current logged user with the list of related data (Content
property).
In my controller, if I put:
Applicationuser user = await _userManager.GetUserAsync(HttpContext.User);
I get the logged user, but without any related data.
But, if I retrieve the current user using the ApplicationDbContext
, like below, I can retrieve the related data:
ApplicationUser user = await _userManager.GetUserAsync(HttpContext.User);
ApplicationUser userWithContent = _context.Users.Include(c => c.Content).Where(u => u.Id == user.Id).ToList();
But this doesn't appear correctly for me!
Any idea?
回答1:
checking the source code of [UserManager][1]
, GetUserAsync will end up calling FindByIdAsync
, which will be provided by an IUserStore
implementation. Looking the source code in the question, very likely using EFCore as the IUserStore implementation.
In case of EFCore, it was mention here that Find
cannot be combined with include
, so I guest what've you done to do eager loading in your question, may actually correct.
回答2:
If you need those properties in every request, there's a better way to get them without query the database in each request.
You can store those properties as Claims
by writing your own IUserClaimsPrincipalFactory<TUser>
and reading them from HttpContext.User
public class CustomUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
{
public CustomUserClaimsPrincipalFactory(UserManager<ApplicationUser> userManager, IOptions<IdentityOptions> optionsAccessor)
: base(userManager, optionsAccessor)
{
}
protected async override Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
ClaimsIdentity identity = await base.GenerateClaimsAsync(user);
identity.AddClaim(new Claim("Name", user.Name));
for (int i = 0; i < user.Content.Count; i++)
{
string content = Newtonsoft.Json.JsonConvert.SerializeObject(user.Content[i]);
identity.AddClaim(new Claim("Content", content));
}
return identity;
}
}
Also you need to register it to service collection
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomUserClaimsPrincipalFactory>();
You can access these properties with this code
string name = httpContext.User.FindFirstValue("Name");
List<Content> contents = new List<Content>();
foreach (Claim claim in httpContext.User.FindAll("Content"))
{
Content content = Newtonsoft.Json.JsonConvert.DeserializeObject<Content>(claim.Value);
contents.Add(content);
};
来源:https://stackoverflow.com/questions/39837355/eager-loading-using-usermanager-with-ef-core