简体   繁体   English

实体框架 - LINQ表达映射多对多

[英]Entity Framework - LINQ Expression Map many to many

I want to find a single User and populate the ICollection<Role> for that user 我想找到一个User并为该User填充ICollection<Role>

I've got users 我有用户

public class User {
   public string Id { get; set; }
   public string UserName { get; set; }
   public ICollection<Role> Roles { get; set; }
}

And the roles 和角色

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

My Database looks like this 我的数据库看起来像这样

在此输入图像描述

I want to get a specific User by Id, all his Roles with a single SQL call. 我想通过Id获得一个特定的用户,所有他的角色只有一个SQL调用。

_context is my DbContext where we can queue User, Roles and UserRoles _context是我的DbContext,我们可以在其中排队User,Roles和UserRoles

With the following sql command I get what data I'm looking for 使用以下sql命令,我得到了我正在寻找的数据

from users in _context.Users
where users.Id == id
join userRoles in _context.UserRoles on users.Id equals userRoles.UserId
join roles in _context.Roles on userRoles.RoleId equals roles.Id
select new
{
    UserID = users.Id,
    UserName = users.UserName,
    RoleID = roles.Id,
    RoleName = roles.Name
};

My problem 我的问题

I want to map this result to the User class, it should create a single user and a ICollection of Roles 我想将此结果映射到User类,它应该创建一个用户和一个ICollection of Roles

在此输入图像描述

How can I achieve this? 我怎样才能做到这一点?

Would it be possible using AutoMapper? 可以使用AutoMapper吗? How? 怎么样?

Thanks in advance! 提前致谢! Alex 亚历克斯

PS: I do not want to use the stores offered by Identity since there is a lot of extra information to be loaded from the database and control the number of calls to it PS:我不想使用Identity提供的商店,因为有很多额外的信息要从数据库加载并控制对它的调用次数

Try following : 试试以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;


namespace ConsoleApplication63
{
    class Program
    {

        static void Main(string[] args)
        {


            Context _context = new Context() {
                UserRoles = new List<UserRole>() {
                    new UserRole() { RoleId = "1", UserId = "1"},
                    new UserRole() { RoleId = "2", UserId = "3"},
                    new UserRole() { RoleId = "3", UserId = "2"},
                    new UserRole() { RoleId = "4", UserId = "4"}
                    },
                Users = new List<User>() {
                    new User() { 
                        Id = "3", UserName = "ABC", Roles = new List<Role> {
                            new Role() { Id = "100", Name = "ABC"},
                            new Role() { Id = "101", Name = "DEF"},
                            new Role() { Id = "102", Name = "GHI"},
                            new Role() { Id = "103", Name = "JKL"},
                            new Role() { Id = "104", Name = "MNO"}
                        }
                    }
                },
                Roles = new List<Role>() {
                    new Role() { Name = "XYZ", Id = "2"}
                }
            };


            string id = "3";
            List<UserRole> results = (from users in _context.UserRoles
                where users.UserId == id
                join  user in  _context.Users  on users.UserId equals user.Id
                join role in _context.Roles on users.RoleId  equals role.Id
                select   new  { Roles = user.Roles, UserId = user.Id})
                .Select(x => x.Roles.Select(y => new UserRole() { RoleId = y.Id, UserId = x.UserId}).ToList()).FirstOrDefault();
        }


    }
    public class Context
    {
        public List<User> Users { get; set; }
        public List<Role> Roles{ get; set; }
        public List<UserRole> UserRoles{ get; set; }
    }
    public class UserRole
    {
        public string UserId { get; set; }
        public string RoleId { get; set; }
    }
    public class User {
       public string Id { get; set; }
       public string UserName { get; set; }
       public List<Role> Roles { get; set; }
    }


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



}

I think you need to use GroupBy to group your result and use an appropriate projection for the Roles collection. 我认为您需要使用GroupBy对结果进行分组,并对Roles集合使用适当的投影。 Considering your initial query, you could do the following (I am using the fluent syntax, you can convert it to query syntax): 考虑到您的初始查询,您可以执行以下操作(我使用的是流畅的语法,您可以将其转换为查询语法):

var initialQuery = from users in _context.Users
            where users.Id == id
            join userRoles in _context.UserRoles on users.Id equals userRoles.UserId
            join roles in _context.Roles on userRoles.RoleId equals roles.Id
            select new
            {
                UserID = users.Id,
                UserName = users.UserName,
                RoleID = roles.Id,
                RoleName = roles.Name
            };

IEnumerable<User> result = initialQuery
                .GroupBy(x => new { x.UserID, x.UserName })
                .Select(x => new User
                {
                    Id = x.Key.UserID,
                    UserName = x.Key.UserName,
                    Roles = x.Select(a => new Role { Id = a.RoleID, Name = a.RoleName }).ToList() as ICollection<Role>
                });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM