英文:
ASP.NET Core Identity, load user's claims when pulling a user from the database
问题
如果你的数据库上下文继承自IdentityDbContext<User>
,那么你的上下文会获得像UserClaims
和RoleClaims
这样的属性。可以使用以下方式获取用户的声明...
User jim = await Context.Users.SingleAsync(u => u.Name == "Jim");
List<IdentityUserClaim<string>> claims = await Context
.UserClaims
.Where(c => c.UserId == jim.Id)
.ToListAsync();
然而,这种方法似乎有些繁琐。我本来希望能够像下面这样操作...
User jim = await Context.Users
.Include(u => u.UserClaims)
.SingleAsync(u => u.Name == "Jim");
然而,这个代码不会编译。如果你将它更改为包含 u.Claims
,那么它会编译,但会抛出异常... "InvalidOperationException: 表达式'u.Claims'在'Include'操作内无效,因为它不表示属性访问:'t => t.MyProperty'"
我理解这一点,即User
实体没有Claims
导航属性(虽然我不确定Intellisense是如何捕捉到Claims
属性的),但我感到惊讶的是,在设置Identity时为什么没有提供这个功能。
我是否漏掉了什么,还是必须进行两次数据库调用才能获取用户和声明?
英文:
If your database context inherits from IdentityDbContext<User>
, then your context gets properties like UserClaims
and RoleClaims
. These can be used to get (say) a user's claims as follows...
User jim = await Context.Users.SingleAsync(u => u.Name == "Jim");
List<IdentityUserClaim<string>> claims = await Context
.UserClaims
.Where(c => c.UserId == jim.Id)
.ToListAsync();
However, this seems somewhat clunky. I would have expected to be able to do the following...
User jim = await Context.Users
.Include(u => u.UserClaims)
.SingleAsync(u => u.Name == "Jim");
However this doesn't compile. If you change it to include u.Claims
then it compiles, but throws an exception... "InvalidOperationException: The expression 'u.Claims' is invalid inside an 'Include' operation, since it does not represent a property access: 't => t.MyProperty'"
Now I understand this, in that the User
entity doesn't have a Claims
navigation property (although I'm not sure where Intellisense picks up the Claims
property), but I'm surprised that this isn't something provided when you set up Identity.
Am I missing something here, or do I have to make two database calls to get the user and claims?
答案1
得分: 1
是的,你说得对,它默认没有导航属性。
你可以尝试按照这个文档添加导航属性:
public class ApplicationUser : IdentityUser
{
public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
}
Dbcontext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>(b =>
{
// 每个用户可以有多个用户声明
b.HasMany(e => e.Claims)
.WithOne()
.HasForeignKey(uc => uc.UserId)
.IsRequired();
});
}
英文:
Yes,you are right, it doesn't have navigation property by default.
You could try follow this document to add the navigation property yourself:
public class ApplicationUser : IdentityUser
{
public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
}
Dbcontext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>(b =>
{
// Each User can have many UserClaims
b.HasMany(e => e.Claims)
.WithOne()
.HasForeignKey(uc => uc.UserId)
.IsRequired();
});
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论