ASP.NET Core Identity,从数据库中提取用户时加载用户的声明

huangapple go评论63阅读模式
英文:

ASP.NET Core Identity, load user's claims when pulling a user from the database

问题

如果你的数据库上下文继承自IdentityDbContext<User>,那么你的上下文会获得像UserClaimsRoleClaims这样的属性。可以使用以下方式获取用户的声明...

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&lt;IdentityUserClaim&lt;string&gt;&gt; Claims { get; set; }
}

Dbcontext:

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity&lt;ApplicationUser&gt;(b =&gt;
        {
            // Each User can have many UserClaims
            b.HasMany(e =&gt; e.Claims)
                .WithOne()
                .HasForeignKey(uc =&gt; uc.UserId)
                .IsRequired();
        });
    }

huangapple
  • 本文由 发表于 2023年6月29日 03:22:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76576146.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定