EF Core 查询 Where 子句是一个集合?

EF Core query where Were clause is a collection?

我正在尝试在 EF Core 中构建一个理智的查询,该查询 returns 是事物的集合,而这些事物又是从事物的集合中派生出来的。基本上在原始 SQL 中会进行 JOIN。

它位于 ASP.NET 核心中,因此初始集合是 SecurityPrincipal 对象上的角色列表:

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();

这个查询很满意,returns 符合预期的组集合。然而,这些组可以访问另一个资源,这是我真正想要的,因为它是多对多的关系,所以有一个桥接 table.

这是我在尝试查询加入 table 的资产组,以便我可以获得映射到 SecurityPrincipal 上的角色的所有组引用的所有资产。

var assetGroupsQuery = dbContext.AssetsGroups.Where(ag => groupsQuery.Any(ag => ag.Id == a.GroupId));
var assetGroups = await assetGroupsQuery.ToListAsync();

当我执行第二个查询时,我的输出中出现了很多垃圾邮件 window:

  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 查询的任何线索?

通常避免在 内存集合 上使用 Any 或除 Contains 以外的任何 LINQ 运算符,就像您的 roles (根据代码应为 IEnumerable<string>).

类型

换句话说,而不是

.Where(g => roles.Any(r => r == g.GroupName))

使用功能等效的

.Where(g => roles.Contains(g.GroupName))

后者保证翻译成SQLIN,而前者则不然。

有趣的是,同时具有误导性的是,EF Core 试图变得聪明,并以与 Contains 相同的方式转换前者,并在执行包含查询时成功,但在用作另一个查询。

可以将其视为当前 EF Core 实现缺陷。但是 workaround/solution 是(如开头所述)不依赖它并始终使用 Contains