我正在尝试使用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
})
}
[如果我删除角色表上的联接,并将into
语句放在UserRole上,则分组的工作方式就像一个超级按钮,但UserRole只是一个链接表,因此Role表是我感兴趣的表。想法如何尽可能简单地分组?谢谢!
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
(您似乎没有使用它),但是如果需要,您应该在此处开始查询并使用导航属性来到达其他实体。] >
此外,我假设您在Role
中还有更多的RoleDto
属性。如果不是,则无需选择Role
实体,因为UserRoles
已包含Role
的Id
。
所以由您决定。您可以信奉一个信条,即存储库调用的作用范围应恰好是一个实体(“单一责任”的非常狭义的定义),或将导航属性用于其发明目的,并考虑对子项负责的汇总根它封装。
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.FirstOrDefault().role.Id
};