ASP.Net 核心 OData - 按嵌套匹配数过滤

ASP.Net Core OData - filter by number of nested matching

我有一个根 Company 实体,有 CompanyType 个子实体。我想过滤所有提供类型的公司。可以在纯 SQL

中创建这样的过滤器
SELECT Companies.Id, Companies.Name
FROM Companies
JOIN (
  SELECT CompanyTypes.CompanyId FROM CompanyTypes
  WHERE CompanyTypes.CompanyTypeId IN (123, 456, 789, 555)
  GROUP BY CompanyId
  HAVING COUNT(*) = 4
) Types ON Companies.ID = Types.CompanyID

也可以使用 linq to sql

创建这样的过滤器
var typeIds = new[] { 123, 456, 789, 555 };
var companies = await EFContext.Companies.Where(company => company.CompanyTypes.Count(type => typeIds.Contains(type.CompanyTypeId)) == typeIds.Length).ToListAsync();

有没有办法使用 odata 语法编写这样的查询?我试过这个

companyTypeIds/any(i: i eq 123) and companyTypeIds/any(i: i eq 456) and companyTypeIds/any(i: i eq 789) and companyTypeIds/any(i: i eq 555)

它给出了预期的结果,但底层查询不同,并且当条件数量增加时它变得非常慢。有没有办法让它像提供的 SQL 查询一样更有效率?后端正在使用 ASP.Net Core 6、EF Core 6、ASP.Net Core OData 8(目前最新)。

拥有要转换为 OData 查询的 SQL 和 LINQ 使这成为一个更容易的命题,WHERE IN ()HAVING COUNT(*) = 4 都可以在 OData 中实现v4.01 和最近改进的支持

Adding support for $count segment in $filter collections in OData WebAPI
In OData core v7.9.0 we added improved support for $count segment in $filter collection properties.

$filter=navProp/$count($filter=prop gt 1) gt 2
$filter=collectionProp/$count($filter=prop gt 1) gt 2

对于此 LINQ:

var typeIds = new[] { 123, 456, 789, 555 };
var companies = await EFContext.Companies.Where(company => 
company.CompanyTypes.Count(type => typeIds.Contains(type.CompanyTypeId)) == 
typeIds.Length).ToListAsync();

以下应该适用于您的查询:

~/Companies?$filter=CompanyTypes/$count($filter=CompanyTypeId in (123, 456, 789, 555) eq 4)