Chr*_*cke 7 c# entity-framework linq-to-sql entity-framework-core ef-core-2.2
我正在尝试在 EF Core 中构建一个理智的查询,该查询返回一组事物,而这些事物又是从事物集合中派生出来的。基本上在原始 SQL 中,会执行 JOIN。
它在 ASP.NET Core 中,因此初始集合是SecurityPrincipal对象上的角色列表:
var roles = User.FindAll(ClaimTypes.Role).Select(r=>r.Value);
Run Code Online (Sandbox Code Playgroud)
这些角色然后映射到我们数据库中的组,所以我可以查找这些:
var groupsQuery = dbContext.Groups.Where(g=>roles.Any(r=>r==g.GroupName));
var groups = await groupsQuery.ToListAsync();
Run Code Online (Sandbox Code Playgroud)
这个查询很愉快,并按预期返回了一组组。然而,这些组可以访问另一个资源,这正是我真正想要的,因为它是多对多的关系,所以有一个桥接表。
这是我尝试查询 AssetGroup 连接表,以便我可以获取映射到SecurityPrincipal.
var assetGroupsQuery = dbContext.AssetsGroups.Where(ag => groupsQuery.Any(ag => ag.Id == a.GroupId));
var assetGroups = await assetGroupsQuery.ToListAsync();
Run Code Online (Sandbox Code Playgroud)
当我执行第二个查询时,我在输出窗口中收到很多垃圾邮件:
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.
Run Code Online (Sandbox Code Playgroud)
关于应该如何表达这样的嵌套查询的任何线索,以便 EF Core 可以正确地编写单个 SQL 查询?
Iva*_*oev 12
通常避免使用Any或之外的任何操作者LINQContains上在存储器收集像您的roles(其中根据码应该是类型IEnumerable<string>)。
换句话说,而不是
.Where(g => roles.Any(r => r == g.GroupName))
Run Code Online (Sandbox Code Playgroud)
使用功能等效的
.Where(g => roles.Contains(g.GroupName))
Run Code Online (Sandbox Code Playgroud)
后者保证被转换为 SQL IN,而前者则不是。
有趣且同时具有误导性的是 EF Core 试图变得聪明,并以与 相同的方式翻译前者Contains,并且在执行包含查询时成功,但在用作另一个查询的一部分时则不成功。
它可以被视为当前的 EF Core 实现缺陷。但是解决方法/解决方案是(如开头所述)不要依赖它并始终使用Contains.