【问题标题】:Many-to-Many with Related ViewModel DTO C#多对多与相关 ViewModel DTO C#
【发布时间】:2020-11-02 19:57:46
【问题描述】:

我在 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"
            }
        ]
    }
]

【问题讨论】:

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


    【解决方案1】:

    我对此的第一印象是您的联接表 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】:

      改变

      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。

      【讨论】:

        【解决方案3】:

        可以在 OnModelCreating 中配置多对多

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

        【讨论】:

          【解决方案4】:

          考虑不包括 -

          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();
          

          【讨论】:

            【解决方案5】:

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

            var users = await _context.Users.Select(x => new { x.Id, x.UserName }).ToListAsync();
            var userRoles = await _context.UserRoles.ToListAsync();
            var roles = await _context.Roles.ToListAsync();
            
            var result = users.Select(x => new
            {
                UserId = x.Id,
                x.UserName,
                Roles = userRoles
                    .Where(y => y.UserId == x.Id)
                    .Join(roles, r => r.RoleId, r => r.Id, (u, r) => new
                    {
                        RoleId = r.Id,
                        RoleName = r.Name
                    }).ToList()
                }); 
            return Ok(result);
            

            【讨论】:

            • 基本上,您正在对数据库进行 三个 次不同的访问,并获取 所有 数据。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-12-12
            • 1970-01-01
            • 2012-06-14
            • 2018-12-16
            • 2020-10-20
            • 1970-01-01
            相关资源
            最近更新 更多