LINQ查询获取包含关联实体的自定义格式字段的实体?

时间:2014-01-17 14:59:15

标签: entity-framework

LINQ上有点生疏 我想从给定用户的相关表中获得单个结果。见下面的架构。 每个用户都有一个或多个角色。我想要一个用户名列表和一个自定义字符串,它是一种格式,例如“Role1 - Role2 - Role3”,其值是与该用户的UserRole / Role相关联的RoleNames。

Role
=====
RoleId
RoleCode
RoleName

UserRole
========
UserRoleId
RoleId
UserId

Users
======
UserId
UserName  

在LINQpad中测试它,我可以获得用户名及其角色的列表,但是我想要结果中的单个字段是所有用户角色的格式化字符串,而不是RoleName,如上所述。< / p>

这是我现在拥有的。如何构建每个用户的角色列表?

from u in Users 
join ur in UserRoles on u.UserId equals ur.UserKey
join r in Roles on ur.RoleKey equals r.RoleId
select new { 
    u.UserId,
    u.UserName,
    r.RoleName
}

2 个答案:

答案 0 :(得分:0)

RoleName分组到UserName上并使用String.Join来获得所需的结果。

from u in Users
join ur in UserRoles on u.UserId equals ur.UserKey
join r in Roles on ur.RoleKey equals r.RoleId
group r.RoleName by u.UserName into grp
select new {
  UserName = grp.Key,
  Roles = String.Join(" - ", grp)
};

这不会返回UserIds。如果它们对结果很重要,则需要将代码更改为

.... join as above
group r.RoleName by new {u.UserId, u.UserName} into grp
select new {
  grp.Key.UserName,
  grp.Key.UserId,
  Roles = String.Join(" - ", grp)
};

这将创建一个包含UserId和UserName的分组键,因此您可以在选择中使用该键。

答案 1 :(得分:0)

按UserName将组添加到LINQ查询中,并使用string.Join格式化由“ - ”分隔的角色。

您可以在LINQPad中测试 -

var Roles = new [] {new{RoleId=1,RoleCode="SU",RoleName="Super User"},new{RoleId=2,RoleCode="PU",RoleName="Power User"}};
var Users = new [] {new{UserId=1,UserName="Bit Shift"},new{UserId=2,UserName="Edward"}};
var UserRoles = new [] {new{UserRoleId=1,RoleId=1,UserId=1},new{UserRoleId=2,RoleId=2,UserId=1},new{UserRoleId=3,RoleId=2,UserId=2}};

var userRoles = from u in Users 
join ur in UserRoles on u.UserId equals ur.UserId
join r in Roles on ur.RoleId equals r.RoleId
select new
{ 
    u.UserId,
    u.UserName,
    r.RoleName
}
into userRole
group userRole by userRole.UserName into userGroups
select new{ UserName=userGroups.Key, Roles = string.Join(" - ", userGroups.Select(ug => ug.RoleName))};
userRoles.Dump();

LINQPad result

更简洁的版本,其中包括结果中的UserId + UserName -

var userRoles = from u in Users 
join ur in UserRoles on u.UserId equals ur.UserId
join r in Roles on ur.RoleId equals r.RoleId
group r by u into userGroups
select new{ User=userGroups.Key, Roles = string.Join(" - ", userGroups.Select(r => r.RoleName))};
userRoles.Dump();

LINQPad result 2

对SQL数据库执行时,需要将查询拆分为两部分,因为LINQ to SQL不支持String.Join,如下所示 -

   var userRoleGroups = (from u in Users 
    join ur in UserRoles on u.UserId equals ur.UserId
    join r in Roles on ur.RoleId equals r.RoleId
    group r by u into userGroups select userGroups)
    .ToList(); // This causes SQL to be generated and executed
    var userRoles = from userGroups in userRoleGroups select(new{ User=userGroups.Key, Roles = string.Join(" - ", userGroups.Select(r => r.RoleName))});
    userRoles.Dump();

或者尝试使用Aggregate而不是String.Join,正如您所建议的那样 -

var userRoles = from u in Users 
join ur in UserRoles on u.UserId equals ur.UserId
join r in Roles on ur.RoleId equals r.RoleId
group r by u into userGroups 
select(new{ 
    User=userGroups.Key,
    Roles = userGroups.Select(s => s.RoleName).Aggregate((current, next) =>  current + " - " + next)});
userRoles.Dump();