EF CORE PostgreSQL - 检查一个列表的所有元素是否包含在另一个列表中

EF CORE PostgreSQL - Check if ALL elements of a List are contained in another List

我正在 Entity framework 中寻找一种方法来检查一个列表的所有元素是否都包含在另一个列表中。

我的应用程序是 .NET 6,我正在使用 Npgsql 查询我的 PostgreSQL 数据库,我有一个 ID 列表和一个与另一个 table“认证”相关的 class“公司” ".

公司class看起来是这样的:

    public class Company
    {
        public int ID { get; set; }
        public List<Certification> Certifications { get; set; }
        ...
    }

我的认证 class 看起来像这样:

public class Certification
{
    public int ID { get; set; }
    public int? CompanyID { get; set; }
    public CertificationType Type { get; set; }

    public int CategoryID { get; set; }
    public virtual Category Category { get; set; }

    public int? RankingID { get; set; }
    public virtual Ranking Ranking { get; set; }
    ...
}

该查询是一个显示公司的分页查询,它必须在数据库上执行(无客户端查询),我正在尝试使用 LINQ 编写它,但出现以下错误:

The LINQ expression 'opt => DbSet() .Where(c0 => EF.Property<int?>(EntityShaperExpression: ALPHUBs.ML.Models.Company ValueBufferExpression: ProjectionBindingExpression: EmptyProjectionMember IsNullable: False , "ID") != null && object.Equals( objA: (object)EF.Property<int?>(EntityShaperExpression: ALPHUBs.ML.Models.Company ValueBufferExpression: ProjectionBindingExpression: EmptyProjectionMember IsNullable: False , "ID"), objB: (object)EF.Property<int?>(c0, "CompanyID"))) .Select(c0 => c0.CategoryID) .Any(p => p == opt)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

我试过这些方法:

IQueryable<Company> query = this._context.Companies.AsNoTracking()
                                                    .Include(c => c.Certifications)
                                                    .AsSplitQuery();

List<int> categoryList = new List<int>() { 1, 3, 5 };

//ATTEMPT 1
query.Where(c => categoryList.All(opt => c.Certifications.Select(cert => cert.CategoryID).Contains(opt)));
//ATTEMPT 2
query.Where(c => categoryList.Except(c.Certifications.Select(cert => cert.CategoryID)).Count() == 0);

我让它工作的唯一方法是:

 c.Certifications.Any(cert => categoryList.Contains(cert.CategoryID));

但这给了我错误的结果,因为我需要所有拥有所有给定认证的公司,而不是至少拥有一个给定认证的公司。

像下面这样的东西怎么样:

var categoryList = new List<int> { 1, 3, 5 };
_ = ctx.Companies
    .Where(c => c.Certifications.Count(c => categoryList.Contains(c.ID)) == categoryList.Count)
    .ToList();

这假定对于给定的公司,最多只有一个具有给定 ID 的认证。