Linq到实体组加入多个表

时间:2015-06-06 11:31:53

标签: c# entity-framework linq-to-entities

我正在尝试使用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表上的连接,并将into语句放在UserRole上,则分组就像一个魅力,但UserRole只是一个链表,所以Role表是我感兴趣的表in。任何想法如何尽可能简单地分组?谢谢!

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

使用导航属性这很容易:

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(你似乎没有使用它),但是如果你需要它,你应该在那里开始查询并使用导航属性来到其他实体。

另外,我假设您在Role中有更多RoleDto个属性。如果没有,则您不需要选择Role个实体,因为UserRoles已包含Role&#39; s Id

所以它取决于你。您可以坚持信条,即存储库调用应限定为一个实体(一个非常狭窄的定义&#34;单一责任&#34;),或者使用导航属性来实现它们的发明,并考虑一个聚合root负责它封装的孩子。

答案 2 :(得分:-1)

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
};