将ASP.Net身份表链接到用户详细信息表 [英] Link ASP.Net Identity table to a user detail table

查看:92
本文介绍了将ASP.Net身份表链接到用户详细信息表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将我的身份用户表链接到我创建的用于跟踪其他用户信息的用户详细信息表.该用户详细信息表称为UserProfile.

I am trying to link my Identity user table to a user detail table I have created to track other user information. That user detail table is called UserProfile.

我遇到了此链接,但在.NET Core 2.1中不起作用: 将ASP.NET身份用户链接到用户详细信息表

I came across this link but it is not working in .NET Core 2.1: Link ASP.NET Identity users to user detail table

这是我目前拥有的:

public class ApplicationUser : IdentityUser
{

    [Key]
    public override string Id { get; set; }

    [ForeignKey("Id")]
    public virtual UserProfile UserProfile { get; set; }

}

[Table("UserProfile")]
public class UserProfile
{
    [Key, ForeignKey("User")]
    public string UserId { get; set; } // UserId (Primary key) 
    public string UserName { get; set; } // UserName 
    public string FirstName { get; set; } // FirstName
    public string LastName { get; set; } // LastName

    //[ForeignKey("Id")]
    public virtual ApplicationUser User { get; set; }
}

但是,在我调用的代码的其他地方:

However, elsewhere in the code I call:

var user = await _userMgr.FindByNameAsync(model.UserName);

并且user.UserProfile为空.

And user.UserProfile is null.

我尝试了数据注释甚至流畅的api的许多组合都无济于事.

I have tried many combinations of data annotations and even fluent api to no avail.

   modelBuilder.Entity<ApplicationUser>()
       .HasOne(c => c.UserProfile)
       .WithOne(t => t.User)
       .HasForeignKey<UserProfile>(b => b.UserId);

我还尝试打开延迟加载,但是甚至无法加载该属性.

I also tried turning on lazy loading but that couldn't even load the property.

有人知道如何在.Net Core 2.1中做到这一点吗?

Does anyone know how to do this in .Net Core 2.1?

谢谢

推荐答案

您的主要问题仅仅是UserManager没有包含相关实体(例如您的UserProfile)的功能.因此,您有两个选择:

Your main issue is simply that UserManager has no functionality to include related entities, such as your UserProfile. As a result, you have two options:

  1. 直接使用您的上下文.然后,您只需一个查询就可以将UserProfileApplicationUser实例一起加载到数据库中:

  1. Use your context directly instead. Then you can eagerly load your UserProfile along with the ApplicationUser instance, in just one query to the database:

var user = await _context.Users.Include(x => x.UserProfile).SingleOrDefaultAsync(x => x.UserName ==  model.UserName);

  • 您可以改为显式加载相关的UserProfile.但是,这将导致额外的查询,总共查询两个:一个查询用户,另一个查询相关的个人资料:

  • You can explicitly load the related UserProfile instead. This will result in an extra query, though, for a total of two: one to get the user and one to get the related profile:

    await _context.Entry(user).Reference(x => x.UserProfile).LoadAsync();
    

  • 但是,坦率地说,您根本不应该拥有UserProfile. ASP.NET身份与ASP.NET成员资格不同.对于后者,您必须有一个单独的UserProfile,因为成员资格中的用户"是不可扩展的.在Identity中,用户 是可扩展的,因此,如果要在其上添加其他配置文件信息,只需将其添加到类中即可:

    However, frankly, you should not have UserProfile at all. ASP.NET Identity is not like ASP.NET Membership. With the latter, you had to have a separate UserProfile because the "user" in Membership was not extensible. In Identity, the user is extensible, so if you want additional profile information on it, just add it to the class:

    public class ApplicationUser : IdentityUser
    {
        public string FirstName { get; set; } // FirstName
        public string LastName { get; set; } // LastName
    }
    

    请注意,我也在这里修剪了很多碎屑.覆盖Id然后使其自动实现没有意义.另外,您显然不需要UserProfile中的UserName属性,因为IdentityUser已经具有该属性,这当然意味着您的ApplicationUser也具有它.

    Note that I trimmed a lot of cruft here as well. There's no point in overriding the Id and then leaving it auto-implemented. Additionally, you obviously don't need the UserName property from UserProfile because IdentityUser already has that, which then of course means your ApplicationUser has it as well.

    更新

    用户数据的持久存储方式不必影响是否可以声明.换句话说,您不必按字面意义将数据另存为声明即可访问它.只需从UserClaimsPrincipalFactory<TUser>派生,覆盖CreateAsync,然后将其注册到作用域内的服务集合即可.

    How the user data is persisted doesn't have to affect whether it can be a claim or not. In other words, you don't have to literally save data as claim in order to access it as claim. Just derive from UserClaimsPrincipalFactory<TUser>, override CreateAsync, and then register it with service collection as scoped.

    public class MyClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
    {
        public MyClaimsPrincipalFactory(UserManager<TUser> userManager, IOptions<IdentityOptions> optionsAccessor)
            : base(userManager, optionsAccessor)
        {
        }
    
        public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
        {
            var principal = await base.CreateAsync(user);
            ((ClaimsIdentity)principal.Identity).AddClaims(new[]
            {
                new Claim(ClaimTypes.GivenName, user.FirstName),
                new Claim(ClaimTypes.Surname, user.LastName),
                // etc.
            });
    
            return principal;
        }
    }
    

    然后在ConfigureServices

    services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, MyClaimsPrincipalFactory>();
    

    这篇关于将ASP.Net身份表链接到用户详细信息表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆