我正在尝试在EF Core中建立一个合理的查询,该查询返回从事物集合派生的事物集合。基本上,在原始SQL中,可以执行JOIN。
它位于ASP.NET Core中,因此初始集合是SecurityPrincipal
对象上的Roles列表:
var roles = User.FindAll(ClaimTypes.Role).Select(r=>r.Value);
这些角色然后映射到我们数据库中的组,所以我可以查找它们:
var groupsQuery = dbContext.Groups.Where(g=>roles.Any(r=>r==g.GroupName));
var groups = await groupsQuery.ToListAsync();
此查询非常满意,并按预期返回了一组组。但是,这些组可以访问另一种资源,这是我真正想要的,并且因为它与多对多关系存在桥接表。
这是我试图查询AssetGroup联接表,以便获取映射到SecurityPrincipal
上的角色的所有组引用的所有资产。
var assetGroupsQuery = dbContext.AssetsGroups.Where(ag => groupsQuery.Any(ag => ag.Id == a.GroupId));
var assetGroups = await assetGroupsQuery.ToListAsync();
执行第二个查询时,我的输出窗口中收到很多垃圾邮件:
The LINQ expression 'where ([ag].Id == [ag].GroupId)' could not be translated and will be evaluated locally.
The LINQ expression 'Any()' could not be translated and will be evaluated locally.
The LINQ expression 'where {from Group g in __groups_0 where ([ag].Id == [ag].GroupId) select [ag] => Any()}' could not be translated and will be evaluated locally.
The LINQ expression 'where ([ag].Id == [ag].GroupId)' could not be translated and will be evaluated locally.
The LINQ expression 'Any()' could not be translated and will be evaluated locally.
关于如何使用这样的嵌套查询措辞的任何线索,以便EF Core可以正确地组成一个SQL查询?
答案 0 :(得分:3)
通常应避免在内存集合中的{em>上使用Any
或Contains
以外的任何LINQ运算符,例如roles
(根据代码,输入IEnumerable<string>
)。
换句话说,代替
.Where(g => roles.Any(r => r == g.GroupName))
使用功能等效的
.Where(g => roles.Contains(g.GroupName))
保证将后者转换为SQL IN
,而不能将后者转换为SQL Contains
。
有趣的是,同时引起误解的是,EF Core试图变得聪明并以与Contains
相同的方式翻译前者,并在执行包含查询时成功,但在用作其他查询的一部分时未成功
可以将其视为当前的EF Core实现缺陷。但是,解决方法/解决方案是(如开头所述)不依赖它,而始终使用get-pip.py
。