Eager Loading using UserManager with EF Core

人盡茶涼 提交于 2020-01-23 04:50:32

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!