通过 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=34
和 year=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 ) ) );
根据需要添加包含和其他谓词
使用 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=34
和 year=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 ) ) );
根据需要添加包含和其他谓词