The*_*bbs 4 .net asp.net-identity entity-framework-core asp.net-core asp.net-core-2.1
我正在尝试将我的 Identity 用户表链接到我创建的用于跟踪其他用户信息的用户详细信息表。该用户详细信息表称为 UserProfile。
我遇到了这个链接,但它在 .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; }
}
Run Code Online (Sandbox Code Playgroud)
但是,在我调用的代码中的其他地方:
var user = await _userMgr.FindByNameAsync(model.UserName);
Run Code Online (Sandbox Code Playgroud)
并且 user.UserProfile 为空。
我尝试了很多数据注释的组合,甚至连流畅的api都无济于事。
modelBuilder.Entity<ApplicationUser>()
.HasOne(c => c.UserProfile)
.WithOne(t => t.User)
.HasForeignKey<UserProfile>(b => b.UserId);
Run Code Online (Sandbox Code Playgroud)
我也尝试打开延迟加载,但这甚至无法加载该属性。
有谁知道如何在 .Net Core 2.1 中做到这一点?
谢谢
您的主要问题只是UserManager
没有包含相关实体的功能,例如您的UserProfile
. 因此,您有两个选择:
直接使用您的上下文。然后,您可以急切地加载您UserProfile
的ApplicationUser
实例,只需对数据库进行一次查询:
var user = await _context.Users.Include(x => x.UserProfile).SingleOrDefaultAsync(x => x.UserName == model.UserName);
Run Code Online (Sandbox Code Playgroud)您可以显式加载相关内容UserProfile
。但是,这将导致额外的查询,总共有两个:一个获取用户,一个获取相关配置文件:
await _context.Entry(user).Reference(x => x.UserProfile).LoadAsync();
Run Code Online (Sandbox Code Playgroud)但是,坦率地说,您根本不应该拥有UserProfile
。ASP.NET Identity 与 ASP.NET Membership 不同。对于后者,您必须有一个单独的,UserProfile
因为 Membership 中的“用户”是不可扩展的。在 Identity 中,用户是可扩展的,因此如果您想要关于它的其他配置文件信息,只需将其添加到类中:
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; } // FirstName
public string LastName { get; set; } // LastName
}
Run Code Online (Sandbox Code Playgroud)
请注意,我也在这里修剪了很多杂物。覆盖Id
然后让它自动实现是没有意义的。此外,您显然不需要该UserName
属性,UserProfile
因为IdentityUser
已经拥有该属性,这当然意味着您ApplicationUser
也拥有它。
更新
用户数据的持久化方式不一定会影响它是否可以声明。换句话说,您不必将数据逐字保存为声明,以便将其作为声明访问。只需派生自UserClaimsPrincipalFactory<TUser>
、覆盖CreateAsync
,然后将其注册到服务集合作为范围。
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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后在ConfigureServices
:
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, MyClaimsPrincipalFactory>();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1962 次 |
最近记录: |