Linq to 实体组连接多个表

Linq to entities group join on multiple tables

我正在尝试对具有一对多关系的多个 table 执行组加入,使用 into 而不是 group by。但有些事情是不对的。我得到了用户拥有的每个角色的重复记录。

from compUsr in Repository.All<CompanyUser>()
join usr in Repository.All<User>() on compUsr.UserId equals usr.Id
join usrRole in Repository.All<UserRole>() on usr.Id equals usrRole.UserId
join role in Repository.All<Role>() on usrRoles.RoleId equals role.Id into roles
    select new UserDTO()
    {
        Id = usr.Id,
        Email = usr.Email
        Roles = roles.Select(r => new RoleDTO()
        {
            Id = r.Id
        })
    }

如果我删除 Role table 上的连接,并将 into 语句放在 UserRole 上,分组就像一个魅力,但 UserRole 只是一个链接 table,所以角色 table 是我感兴趣的角色。有什么想法可以尽可能简单地对其进行分组吗?谢谢!

from compUsr in Repository.All<CompanyUser>()
join usr in Repository.All<User>() on compUsr.UserId equals usr.Id
join usrRole in Repository.All<UserRole>() on usr.Id equals usrRole.UserId
join role in Repository.All<Role>() on usrRoles.RoleId equals role.Id
group new { usr, role } by usr into grp
                    select new
                    {
                        Id = grp.Key.Id,
                        Email = grp.Key.Email,
                        Roles = grp.Select(r => new RoleDTO()
                        {
                            Id = r.role.Id
                        })
                    };

导航属性是有原因的。他们使代码更加简洁和声明。

有了导航属性,这会很容易:

from usr in context.Users // or Repository.All<User>()
select new UserDto
{
    Id = usr.Id,
    Email = usr.Email,
    Roles = usr.UserRoles.Select(ur => ur.Roles)
               .Select(r => new RoleDTO()
                            {
                                Id = r.Id
                            }
}

我不知道你为什么也加入CompanyUser(你好像没有用),但是如果你需要的话,你应该从那里开始查询并使用导航属性来到达其他实体。

此外,我假设您在 RoleDto 中有更多 Role 个属性。如果不是,则不需要 select Role 实体,因为 UserRoles 已经包含 RoleId.

所以这取决于你。您可以坚持这样的信条,即存储库调用应仅限于一个实体("single responsibility" 的非常狭窄的定义),或者使用导航属性来实现它们的发明目的,并考虑一个聚合根负责它封装的子项。

from compUsr in Repository.All<CompanyUser>()
join usr in Repository.All<User>() on compUsr.UserId equals usr.Id into eGroup
from u in eGroup.DefaultIfEmpty()
join usrRole in Repository.All<UserRole>() on u.Id equals usrRole.UserId into eGroup1
from ur in eGroup1.DefaultIfEmpty()
join role in Repository.All<Role>() on ur.RoleId equals role.Id into eGroup2
from r in eGroup2.DefaultIfEmpty()
group new { u, r } by u into grp
select new
{
      Id = grp.Key.Id,
      Email = grp.Key.Email,
      Roles = grp.FirstOrDefault().r.Id
};