C# Linq到多个表上的实体组联接
我正在尝试对具有一对多关系的多个表执行组联接,使用C# Linq到多个表上的实体组联接,c#,entity-framework,linq-to-entities,C#,Entity Framework,Linq To Entities,我正在尝试对具有一对多关系的多个表执行组联接,使用into而不是groupby。但有些事情是不对的。我为用户的每个角色获取重复记录 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
into
而不是groupby
。但有些事情是不对的。我为用户的每个角色获取重复记录
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
})
}
来自存储库中的compUsr.All()
在compUsr.UserId上的Repository.All()中加入usr等于usr.Id
在usr.Id上的Repository.All()中加入usrRole等于usrRole.UserId
将usrRoles.RoleId上Repository.All()中的角色等于role.Id加入到角色中
选择newuserdto()
{
Id=usr.Id,
Email=usr.Email
角色=角色。选择(r=>newroledto()
{
Id=r.Id
})
}
如果我删除角色表上的join,并将放在UserRole上的
语句中,分组就像一个符咒,但是UserRole只是一个链接表,所以角色表就是我感兴趣的表。有没有办法把这些尽可能简单地分组?谢谢 来自存储库中的compUsr.All()
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
})
};
在compUsr.UserId上的Repository.All()中加入usr等于usr.Id
在usr.Id上的Repository.All()中加入usrRole等于usrRole.UserId
在usrRoles.RoleId上的Repository.All()中加入角色等于role.Id
由usr将新的{usr,role}分组到grp中
选择新的
{
Id=grp.Key.Id,
Email=grp.Key.Email,
Roles=grp.Select(r=>newroledto()
{
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
}
}
context.Users//或Repository.All()中的usr中的
选择newuserdto
{
Id=usr.Id,
Email=usr.Email,
Roles=usr.UserRoles.Select(ur=>ur.Roles)
.选择(r=>新角色到()
{
Id=r.Id
}
}
我不知道为什么您也加入了公司用户
(您似乎没有使用它),但是如果您需要它,您应该在那里开始查询,并使用导航属性访问其他实体
另外,我假设您在RoleDto
中有更多的Role
属性。如果没有,您不需要选择Role
实体,因为UserRoles
已经包含Role
的Id
<> P>这取决于你。你可以坚持一个信条:一个库调用应该被范围化为一个实体(一个非常狭隘的“单一责任”的定义),或者使用导航属性来创建它们,并考虑一个负责它封装的孩子的聚合根。代码>从库中的COMPUSR。
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
};
将compUsr.UserId等于usr.Id的Repository.All()中的usr加入到eGroup中
来自eGroup.DefaultIfEmpty()中的u
将u.Id上的usrRole.UserId上的usrRole.All()加入到eGroup1中
来自eGroup1.DefaultIfEmpty()中的ur
将ur.RoleId等于role.Id的Repository.All()中的角色加入到eGroup2中
来自eGroup2.DefaultIfEmpty()中的r
将新的{u,r}按u分组到grp中
选择新的
{
Id=grp.Key.Id,
Email=grp.Key.Email,
Roles=grp.FirstOrDefault().r.Id
};
对需要更改哪些内容才能使代码正常工作的一些解释将对原始海报和未来用户有所帮助。使用FirstOrDefault()方法,您可以以简单的方式访问任何相关字段,并按您想要的任何字段(usr、角色)分组,而无需重复数据(完整的代码片段)。