通过 EF Core 中的孙属性过滤父集合

Filtering parent collection by grandchildren properties in EF Core

使用 EF 核心 5 和 ASP.NET 核心 3.1,我试图根据其孙子集合的条件获取过滤集合。 我有以下实体:

public class Organisation
{
        public int Id { get; set; }
        public int? OrganisationId { get; set; }
        public IEnumerable<Customer> Customers { get; set; }
}

public partial class Customer
{
        [Key]
        public uint Id { get; set; }
        public int? EmployerId { get; set; }
        public int? OrganisationId { get; set; }
        public List<TimecardProperties> TimecardsProperties { get; set; }
}

public partial class TimecardProperties
{     
        [Key]
        public int Id { get; set; }
        public int? EmployerId { get; set; }
        public int? Week { get; set; }
        public short? Year { get; set; }
}

目标是让所有组织至少拥有一位客户,并且该客户至少有 1 张考勤卡 属性 位于 week=34year=2021.

到目前为止,我已经尝试了以下方法:

////necessary join to get Organisations for user id
            IQueryable<Organisation> ouQuery = (from cou in _dbContext.Organisations
                           join uou in _dbContext.table2 on cou.OrganisationId equals uou.OrganisationId                           
                           where uou.UsersId == int.Parse(userId)                          
                           select cou)
                           .Where(cou => cou.Customers.Where(c => c.TimecardsProperties.Count > 0).Any())
                           .Include(cou => cou.Customers.Where(c => c.TimecardsProperties.Count > 0))
                        .ThenInclude(c => c.TimecardsProperties.Where(tc => tc.tWeek == 34 && tc.Year > 2020))
                             ;

这个 return 是一个 organisation 列表,每个列表都有一个 customers 列表,但有些客户的计数是 timecards 0。我不想 organisation 在 returned 列表中没有至少一项在 timecards 集合中。

此外,它太慢了,如果我尝试过滤生成的列表,它甚至 较慢(超过 15 秒)

我也曾在 organisation db context 上尝试过原始 sql 查询,但它还是很慢:

select distinct count(id) from organisation a where organisation_id  in (
select organisation_id from customers where employer_id in (select distinct employer_id from timecards a
inner join timecard_components b on a.id=b.timecards_id
where week IN(
34) and year in (2021,2021) and invoice !=0 and type = 'time'
 group by employer_id, week)
);

总的来说,我想知道总数 returned organisation 集合的分页计数(因此我不需要包括每个实体的所有属性) 以及 return 只有 正确 结果的一部分,满足条件, 一个 organisation 列表,其中至少有 1 timecards 他们 customers 最后执行查询,如下所示:

ouQuery.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync();

我也尝试了 EntityFramework.Plus 和投影,但没有结果。 我如何编写此代码才能获得 organisation 列表的总数以及这些结果的一部分(前 10 个)以显示给用户?

使用导航属性。这是您要查询的内容:

var orgsQuery = dbContext.Organizations
    .Where( o => o.Customers.Any( c =>
        c.TimecardProperties.Any( tp =>
            tp.Year = 2021
            && tp.Week = 34 ) ) );

根据需要添加包含和其他谓词