这是这里提出的一个附加问题: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
进行以下操作:
- 获取
RoleNames
的列表 - 通过检查特定的
RoleName
,在queryResult
上执行单独的LINQ查询 - 执行
.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
表(我正在简化您的长标识符,这不是问题的一部分,而且打字太多(。
Roles
和Users
之间似乎存在多对多的关系:每个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;