如何将两个联接表中的 IQueryable LINQ 结果返回到一个列表中<string>?



这是这里提出的一个附加问题:Entity Framework Core 5.0如何将LINQ转换为多对多联接以使用ASP的交集表。NET会员

如何将以下LINQIQueryable结果(来自两个联接表(的RoleName列的结果返回到List<string>

var queryResult = (this.DbContext.aspnet_UsersInRoles
.Where(x => x.UserId == dpass.UserId)
.Join(
this.DbContext.aspnet_Roles,
ur => ur.RoleId,
r => r.RoleId,
(ur, role) => new
{
ur,
role
}
)
.Select(x => new { x.ur.UserId, x.role.RoleName })
);

更新1

我需要值数组形式的List,这样我就可以使用Contains()方法。我需要搜索分配给UserId的特定RoleNames。如果我在IQueryable上使用ToList(),那么数组结果的形式为:

{RoleName="admin"}

{角色名称="用户"}

我无法使用.Contains()方法,因为我收到以下错误:

无法从"string"转换为<匿名类型:string RoleName>

这似乎是在期待一个可以将查询结果分配给的类。但是,一个类并不存在,因为我正在动态执行。

更新2

我需要列表中的queryResult,该列表的形式为:

{quot;admin"}

{"用户"}

有了这个输出,我可以使用.Contains()方法执行多个检查。这用于确定Windows Forms字段属性。因此,如果UserId属于admin角色,则表单启用某些复选框和单选按钮,而如果UserId属于user角色,则该表单启用不同的复选框。这并不是一个完整的可用角色列表以及表单执行的检查。但是,重要的是,List上有多个检查需要在单独的IF语句中执行。

目前,我可以使用queryResult进行以下操作:

  1. 获取RoleNames的列表
  2. 通过检查特定的RoleName,在queryResult上执行单独的LINQ查询
  3. 执行.Count() > 0检查,查看UserId是否处于特定角色

这似乎是一个丑陋的破解,因为我有一个中间步骤,即通过LINQ创建要检索的1 + N变量,并存储每个RoleName,然后检查.Count()是否大于零。我认为List方法会更清洁、更有效。如果可能的话。

var varUser = from d in queryResult
where d.RoleName == "user"
select new { d.RoleName };
var varAdmin = from u in queryResult
where u.RoleName == "admin"
select new { u.RoleName };
//... more declarations and LINQs ...

简短回答:
仅选择RoleName,并使用SelectMany而不是Select

更好的答案

因此,您有一个Roles表和一个Users表(我正在简化您的长标识符,这不是问题的一部分,而且打字太多(。

RolesUsers之间似乎存在多对多的关系:每个Role都是零个或多个Users的角色,每个User都有零个或更多个角色。

这种多对多关系是使用标准连接表UsersInRoles来实现的。此连接表有两个外键:一个指向用户,另一个指向角色。

您有一个UserId,并且似乎需要具有该Id的用户的所有角色的所有名称。

这个怎么样:

int userId = ...
// Get the names of all Roles of the User with this Id
var namesOfRolesOfThisUser = dbContext.UsersInRoles
// only the user with this Id:
.Where(userInRole => userInRole.UserId == userId)
// get the names of all Roles for this userInRole
.SelectMany(userInRole => dbContext.Roles.Where(role => role.RoleId == userInRole.RoleId)
.Select(role => role.RoleName));

换句话说:从UsersInRoles表中,只保留那些属性UserId值等于UserId的UsersInRolles。

从剩余的每个UsersInRole中,选择具有请求UserInRole的RoleId的所有角色。角色Id。从这些角色中获取RoleName。

我使用SelectMany来确保我得到一个字符串序列,而不是一个字符串的序列。

如果怀疑是双重RoleNames,请考虑在末尾附加Distinct()

但我想加入

有些人真的很喜欢自己加入。

int userId = ...
var namesOfRolesOfThisUser = dbContext.UsersInRoles
.Where(userInRole => userInRole.UserId == userId)
.Join(dbContext.Roles,
userInRole => userInRole.RoleId,  // from every UserInRole take the foreign key
role => role.RoleId,              // from every Role take the primary key
// when they match, take only the name of the Role
(userInRole, role) => role.RoleName);

尝试使用GroupBy((。请注意,IQueryable到SQL的直接转换不支持此方法。如果您尝试在.ToList()之前调用GroupBy(),它将抛出一个错误。

在你的例子中,你可以这样做:在内存中选择一个列表,然后使用它:

var queryResult = (this.DbContext.aspnet_UsersInRoles
.Where(x => x.UserId == dpass.UserId)
.Join(this.DbContext.aspnet_Roles,
ur => ur.RoleId,
r => r.RoleId,
(ur, role) => new { ur, role }
)
.Select(x => new { x.ur.UserId, x.role.RoleName })
.ToList()   // MATERIALIZE FIRST
.GroupBy(x => x.UserId)  //ADD THIS
);

queryResult.Contains(roleName=> roleName == "ROLE_TO_SEARCH")
var userId = queryResult.Key;

最新更新