Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何同时获取标识用户及其角色的列表?_C#_Entity Framework Core_Roles_Asp.net Core Identity - Fatal编程技术网

C# 如何同时获取标识用户及其角色的列表?

C# 如何同时获取标识用户及其角色的列表?,c#,entity-framework-core,roles,asp.net-core-identity,C#,Entity Framework Core,Roles,Asp.net Core Identity,聊天信息模型: public class ChatMessage { [Key] public long Id { get; set; } [Required] public string Content { get; set; } [Required] public DateTime TimePosted { get; set; } public string AuthorId { get; set; } [Required, ForeignKey(

聊天信息模型:

public class ChatMessage
{
    [Key] public long Id { get; set; }

    [Required] public string Content { get; set; }
    [Required] public DateTime TimePosted { get; set; }

    public string AuthorId { get; set; }
    [Required, ForeignKey("authorId")] public ApplicationUser Author { get; set; }
}
现在,我想获得某一天的聊天信息列表,同时知道其作者是否担任“Voice”角色:

var messages=await dbContext.ChatMessages.AsNoTracking()
.Where(chm=>chm.TimePosted.Date==someDateTime.Date).OrderBy(chm=>chm.TimePosted)
.ToListAsync();
var result=新列表{};
foreach(消息中的var m)
Add(Tuple.Create(m,wait userManager.IsInRoleAsync(Author,“Voice”));
据我所知,这将向数据库发送与要获取的聊天信息数量相同的查询,这似乎令人讨厌,因为这应该只在一个查询中完成,不是吗?或者至少是一个固定数量的查询,但不是线性的


我做错了吗?如果是,我应该怎么做?

您应该能够
包括
ApplicationUser
索赔
表,并在查询中完成所有操作

我尚未对此进行全面测试,但大致如下:

dbContext.ChatMessages
    .Include(i => i.Author)
    .Include(i => i.Author.Claims)
    .Where(w => w.Author.Claims.Any(a => a.ClaimType == ClaimTypes.Role 
                                         && a.ClaimValue == "Voice"));

这就是我现在拥有的。未经测试,但似乎没有给出编译错误:

string voiceRoleId = (await roleManager.FindByNameAsync("Voice")).Id;
var result = await dbContext.ChatMessages.AsNoTracking()
    .Where(chm => chm.TimePosted.Date == someDateTime.Date).OrderBy(chm => chm.TimePosted)
    .GroupJoin(
        dbContext.UserRoles.Where(ur => ur.RoleId == voiceRoleId),
        chm => chm.AuthorId, r => r.UserId,
        (chm, rs) => new { Message = chm, IsVoice = rs.Any() }
    ).ToListAsync();

这是。。。有点不可思议。我认为这项任务比8行代码要简单。

正确的方法似乎来自@Kirk Larkin's,我将其转换为答案,因为它比注释更直观,而且注释可能随时消失

他链接了这个文档页面:,上面写着:

基础的实体框架(EF)核心导航属性 已删除IdentityUser POCO(普通旧CLR对象)。如果你的 1.x project使用了这些属性,请手动将它们添加回2.0项目:C#


不幸的是,尝试过这样做后,在类似IdentityUser的声明或角色上似乎没有任何导航属性您的
ApplicationUser
是什么样子的?它只包含一个与此问题索引无关的属性:
public class ApplicationUser:IdentityUser{public List gamesPlayed{get;set;}
应该有助于解释缺少的
声明
角色
属性。这将获得联接表实体,但不是实际角色
author.Roles
是一个
IdentityUserRole
。没有进一步的导航。
string voiceRoleId = (await roleManager.FindByNameAsync("Voice")).Id;
var result = await dbContext.ChatMessages.AsNoTracking()
    .Where(chm => chm.TimePosted.Date == someDateTime.Date).OrderBy(chm => chm.TimePosted)
    .GroupJoin(
        dbContext.UserRoles.Where(ur => ur.RoleId == voiceRoleId),
        chm => chm.AuthorId, r => r.UserId,
        (chm, rs) => new { Message = chm, IsVoice = rs.Any() }
    ).ToListAsync();
/// <summary>
/// Navigation property for the roles this user belongs to.
/// </summary>
public virtual ICollection<IdentityUserRole<int>> Roles { get; } = new List<IdentityUserRole<int>>();

/// <summary>
/// Navigation property for the claims this user possesses.
/// </summary>
public virtual ICollection<IdentityUserClaim<int>> Claims { get; } = new List<IdentityUserClaim<int>>();

/// <summary>
/// Navigation property for this users login accounts.
/// </summary>
public virtual ICollection<IdentityUserLogin<int>> Logins { get; } = new List<IdentityUserLogin<int>>();
protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);
    // Customize the ASP.NET Core Identity model and override the defaults if needed.
    // For example, you can rename the ASP.NET Core Identity table names and more.
    // Add your customizations after calling base.OnModelCreating(builder);

    builder.Entity<ApplicationUser>()
        .HasMany(e => e.Claims)
        .WithOne()
        .HasForeignKey(e => e.UserId)
        .IsRequired()
        .OnDelete(DeleteBehavior.Cascade);

    builder.Entity<ApplicationUser>()
        .HasMany(e => e.Logins)
        .WithOne()
        .HasForeignKey(e => e.UserId)
        .IsRequired()
        .OnDelete(DeleteBehavior.Cascade);

    builder.Entity<ApplicationUser>()
        .HasMany(e => e.Roles)
        .WithOne()
        .HasForeignKey(e => e.UserId)
        .IsRequired()
        .OnDelete(DeleteBehavior.Cascade);
}
var usersAndRoles = await dbContext.ChatMessages.AsNoTracking()
    .Include(msg => msg.Author).ThenInclude(author => author.Roles)
    .Select(msg => new { Message = msg, IsVoice = msg.Author.Roles.Contains("Voice") })
    .ToListAsync();