我对 Entity Framework 很陌生,所以我现在很困惑。我有这两个问题:
var usersQuery =
from role in this.dbContext.Set<Model.ApplicationRole>()
join ru in dbContext.Set<Model.ApplicationRoleUser>() on role.Id equals ru.ApplicationRoleId into rus
from ru in rus.DefaultIfEmpty()
join user in dbContext.Set<Model.User>() on ru.UserId equals user.Id into users
from user in users.DefaultIfEmpty()
where
(ru != null && ru.ApplicationId == application.Id)
&& (roleId == null || ru.ApplicationRoleId == roleId.Value)
group role by user into grps
select
new RoleActor
{
Actor =
new Actor
{
AccountName = grps.Key.AccountName,
DisplayName =
(grps.Key.DisplayName ?? string.Empty) != string.Empty
? grps.Key.DisplayName
: grps.Key.CommonName,
DomainName = grps.Key.DomainName,
Email = grps.Key.Email ?? string.Empty,
CompanyCode = grps.Key.CompanyCode,
AdGuid = grps.Key.AdGuid,
CommonName = grps.Key.CommonName
},
Type = Model.ActorType.User,
RoleNames = grps.Select(role => role.Name).ToList()
};
var groupsQuery =
from role in this.dbContext.Set<Model.ApplicationRole>()
join rg in dbContext.Set<Model.ApplicationRoleGroup>() on role.Id equals rg.ApplicationRoleId into rgs
from rg in rgs.DefaultIfEmpty()
join @group in dbContext.Set<Model.Group>() on rg.GroupId equals @group.Id into groups
from @group in groups.DefaultIfEmpty()
where
(rg != null && rg.ApplicationId == application.Id)
&& (roleId == null || rg.ApplicationRoleId == roleId.Value)
group role by @group into grps
select
new RoleActor
{
Actor =
new Actor
{
AccountName = grps.Key.AccountName,
DisplayName =
(grps.Key.DisplayName ?? string.Empty) != string.Empty
? grps.Key.DisplayName
: grps.Key.CommonName,
DomainName = grps.Key.DomainName,
Email = string.Empty,
CompanyCode = string.Empty,
AdGuid = grps.Key.AdGuid,
CommonName = grps.Key.CommonName
},
Type = Model.ActorType.Group,
RoleNames = grps.Select(role => role.Name).ToList()
};
我需要合并这两个查询。但是当我尝试使用扩展方法 Union 时,出现异常:
The 'Distinct' operation cannot be applied to the collection ResultType of the specified argument. Parameter name: argument
我想连接查询然后做类似的事情:
queryConcatResult.GroupBy(x => x.Key).Select(x => x.FirstOrDefault())
但是当我使用 Concat 方法时,出现异常:
The nested query is not supported. Operation1='UnionAll' Operation2='MultiStreamNest'
如有任何提示,我将不胜感激。
最佳答案
不可能(至少对于 EF)执行包含嵌套集合的查询的联合或连接(例如 group by
或 RoleNames
的结果,如您例)。
解决方案是从基本查询中删除分组,创建统一投影,连接然后进行分组。
像这样:
(1)
var usersQuery =
from user in dbContext.Set<Model.User>()
join ru in dbContext.Set<Model.ApplicationRoleUser>() on user.Id equals ru.UserId
join role in this.dbContext.Set<Model.ApplicationRole>() on ru.ApplicationRoleId equals role.Id
where ru.ApplicationId == application.Id
&& (roleId == null || ru.ApplicationRoleId == roleId.Value)
select new
{
Actor = new Actor
{
AccountName = user.AccountName,
DisplayName = (user.DisplayName ?? "") != "" ? user.DisplayName : user.CommonName,
DomainName = user.DomainName,
Email = user.Email ?? "",
CompanyCode = user.CompanyCode,
AdGuid = user.AdGuid,
CommonName = user.CommonName
},
Type = Model.ActorType.User,
Role = role,
};
(2)
var groupsQuery =
from @group in dbContext.Set<Model.Group>()
join rg in dbContext.Set<Model.ApplicationRoleGroup>() on @group.Id equals rg.GroupId
join role in this.dbContext.Set<Model.ApplicationRole>() on rg.ApplicationRoleId equals role.Id
where rg.ApplicationId == application.Id
&& (roleId == null || rg.ApplicationRoleId == roleId.Value)
select new
{
Actor = new Actor
{
AccountName = @group.AccountName,
DisplayName = (@group.DisplayName ?? "") != "" ? @group.DisplayName : @group.CommonName,
DomainName = @group.DomainName,
Email = "",
CompanyCode = "",
AdGuid = @group.AdGuid,
CommonName = @group.CommonName
},
Type = Model.ActorType.Group,
Role = role,
};
(3)
var actorsQuery =
from a in usersQuery.Concat(groupsQuery)
group a by new { a.Actor, a.Type } into g
select new RoleActor
{
Actor = g.Key.Actor,
Type = g.Key.Type,
RoleNames = g.Select(a => a.Role.Name).ToList()
};
旁注:虽然使用 string.Empty
是一个很好的编程习惯,但您最好避免在 EF 查询中使用它,因为 EF 不会将其识别为常量并生成额外的 SQL 查询参数。
关于c# - 如何联合查询复杂对象的两个复杂查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39634302/