与相关ViewModel DTO C#的多对多

时间:2020-11-02 19:57:46

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

我在NetCore C#项目中有3个表,我无法对数据库进行查询以形成具有附加角色的用户的完整列表

用户表

var user = await _context.Users
    .Select(x => new
    {
        x.Id,
        x.UserName           
    }).ToListAsync();

角色表

var role = await _context.Roles
    .Select(x => new
    {
        RoleId = x.Id,
        RoleName = x.Name
    }).ToListAsync();

和UserRole表(关系)

var userRole = await _context.UserRoles
    .Select(x => new
    {
        x.RoleId,
        x.UserId
    }).ToListAsync();

您需要如何为要生成的DTO建立查询?

public class UserRoleDto
{
    public int UserId { get; set; }
    public string UserName { get; set; }

    public IEnumerable<RolesDto> Roles { get; set; }

}

public class RolesDto
{
    public int RoleId { get; set; }

    public string RoleName { get; set; }
}

结果显示出来了吗?

[
    {
        "userId": "1",
        "userName": "User1",
        "roles": [
            {
                "roleId": "1",
                "roleName": "admin"
            },
            {
                "roleId": "2",
                "roleName": "operator"
            },
            {
                "roleId": "3",
                "roleName": "support"
            }
        ]
    },
    {
        "userId": "2",
        "userName": "User2",
        "roles": [
            {
                "roleId": "2",
                "roleName": "operator"
            }
        ]
    }
]

5 个答案:

答案 0 :(得分:0)

更改

public class UserRoleDto
{
    public int UserId { get; set; }
    public string UserName { get; set; }

    public IEnumerable<RolesDto> Roles { get; set; }

}

收件人

public class UserRoleDto
{
    public int UserId { get; set; }
   
 public int RoleId{ get; set; }
}

并进行查询以加入用户和角色。之后,请使用这篇帖子Build JSON Hierarchy from Structured Data转换为json。

答案 1 :(得分:0)

对此的第一印象是您的联接表UserRole可能看起来像这样:

public class UserRole
{
    public int UserId {get; set;}
    public int RoleId {get; set;}
}

哪一个好,但是它缺乏能够满足DTO要求的导航属性。 您应该以拥有一个联接表为目标

public class UserRole
{
    public int UserId {get; set;}
    public int RoleId {get; set;}
    public Role Role {get; set;}
    public User User {get; set;}
}

您几乎可以正确执行查询,它未经测试,但可以尝试如下操作:

var userRole = await _context.UserRoles
    .Select(x => new UserRoleDto()  
    {
       UserId = x.User.Id,
       UserName = x.User.Name,
       Roles = new List<RolesDto>()
       {
           new RolesDto()
           {
              RoleId = x.Role.Id,
              RoleName = x.Role.Name
           }
       }
    }).ToListAsync();

答案 2 :(得分:0)

多对多可以在OnModelCreating中配置

modelBuilder.Entity<User>()
   .HasMany(b => b.Roles)
   .WithMany(c => c.Users)
   .Map(cs =>
   {
       cs.MapLeftKey("UserId");
       cs.MapRightKey("RoleId");
       cs.ToTable("UserToRole");
   });

答案 3 :(得分:0)

考虑不包括-

public DbSet<UserRole> UserRoles { get; set; }
在您的DbContext类中的

。这是因为UserRole是连接实体,而连接实体不是以模型为中心的概念。它们的存在纯粹是一个以关系数据库为中心的思想。因此,请尽量不要直接查询加入实体。

将模型定义为-

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }

    public IList<UserRole> UserRoles { get; set; }
}

public class Role
{
    public int Id { get; set; }
    public string Name { get; set; }

    public IList<UserRole> UserRoles { get; set; }
}

public class UserRole
{
    public int UserId { get; set; }
    public int RoleId { get; set; }

    public User User { get; set; }
    public Role Role { get; set; }  
}

您的查询可以像-

var result = await _context.Users.Select(
    u => new UserRoleDto
    {
        UserId = u.Id,
        UserName = u.Name,
        Roles = u.UserRoles.Select(x => new RolesDto { RoleId = x.RoleId, RoleName = x.Role.Name }).ToList()
    }).ToListAsync();

答案 4 :(得分:0)

我使用给定的解决方案实现了

itertools