c# - 如何在一个查询中获取具有角色的用户?

标签 c# asp.net-core entity-framework-core asp.net-core-identity

我已经像这里描述的那样设置了我的身份模型: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-2.2#add-user-and-role-navigation-properties

所以我的每个用户类都有一个角色集合,通过 UserRole“包装器”。 所有的实体关系都设置好了。

当我查询我的用户时,我得到了每个用户的所有角色(在这里使用延迟加载,但“包含”没有区别):

var users = _userManager.Users
    .AsNoTracking()
    .ToList();

但是在检查 EF Core 创建的日志时,我发现每个用户都有另一个查询来获取角色:

[Parameters=[@_outer_Id='d550f61b-ed3d-4d90-8e7b-31552de50d3b' (Size = 450)], CommandType='"Text"', CommandTimeout='30']
SELECT [r].[RoleId] AS [Id], [r.Role].[Name], [r.Role].[DisplayName]
FROM [AspNetUserRoles] AS [r]
INNER JOIN [AspNetRoles] AS [r.Role] ON [r].[RoleId] = [r.Role].[Id]
WHERE ([r].[Discriminator] = N'UserRole') AND (@_outer_Id = [r].[UserId])

这对我数据库中的每个用户 ID 重复。

怎样才能只用一次查询就得到结果?

以防万一,我的模型:

public class User : IdentityUser
{
    public virtual ICollection<UserRole> UserRoles { get; set; }
}

public class UserRole : IdentityUserRole<string>
{
    public virtual User User { get; set; }
    public virtual Role Role { get; set; }
}

public class Role : IdentityRole
{
    public virtual ICollection<UserRole> UserRoles { get; set; }
}

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

    modelBuilder.Entity<User>(b =>
    {
        b.HasMany(e => e.UserRoles)
            .WithOne(e => e.User)
            .HasForeignKey(ur => ur.UserId)
            .IsRequired();
    });

    modelBuilder.Entity<Role>(b =>
    {
        b.HasMany(e => e.UserRoles)
            .WithOne(e => e.Role)
            .HasForeignKey(ur => ur.RoleId)
            .IsRequired();
    });
}

最佳答案

看起来您启用了延迟加载。 EF 永远不会自动连接相关表,您必须以某种方式指示它这样做。在延迟加载的情况下,这是通过访问导航属性的 getter 来实现的。 EF 覆盖 getter 以从对象缓存中提取相关实体,如果在那里找不到它们,则发出查询以检索它们(因此是“惰性”)。您显然只是在遍历用户并为每个用户访问 UserRoles 成员,这会导致为每个用户发出单独的查询。

您要做的是急切加载关系。您可以通过 Include(对于子关系使用 ThenInclude)执行此操作。换句话说:

var users = await _userManager.Users
    .Include(x => x.UserRoles)
        .ThenInclude(x => x.Role)
    .AsNoTracking()
    .ToListAsync();

关于c# - 如何在一个查询中获取具有角色的用户?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57910856/

相关文章:

c# - 参数类型不可分配给参数类型,它应该是

c# - 以编程方式将行添加到 WPF 窗口中的网格

c# - 我可以使用 ASP.NET Core 6+ WebApplicationBuilder 从 WebApplicationFactory 中排除代码吗?

sql-server - EF Core 存储过程 FromSqlRaw 不提供更新值

c# - Entity Framework 核心;在针对 (MS) SQL Server 的查询中使用 ORDER BY

c# - 从列表中删除数组

c# - 增加 asp.net 应用程序的应用程序超时

c# - Entity Framework 6 中的 Fluent Api 不兼容 Entity Framework Core

azure - ASP.NET Core Azure WebJob 未记录到 Azure 存储

logging - ASP.NET Core 1.0 日志记录