有条件地包含和过滤 EF Core 8 中的相关实体

问题描述 投票:0回答:2

如何查询

Employees
Holidays
集合,以便即使没有找到符合其指定条件的假期,仍会返回符合其条件的员工?

实体:

public class Employee
{
    public Guid Id { get; set; }
    public List<Holiday> Holidays { get; set; } = [];
}

public class Holiday
{
    public Guid Id { get; set; }
    public Guid EmployeeId { get; set; }
    public DateTime Date { get; set; }
}

查询:

我有一个方法需要:

  • 通过 ID 搜索员工
  • 或者
    • 不包括任何假期
    • 包括员工的所有假期(如果有)
    • 包括员工的所有历史性假期(如果存在)
    • 包括员工所有未来的假期(如果存在)
enum IncludeHolidays { None, All, Past, Future }

Employee? GetEmployee(Guid employeeId, IncludeHolidays includeHolidays)
{
    var query = ctx.Employees
        .Where(e => e.Id == employee.Id)
        .AsQueryable();

    if (includeHoliday != IncludeHolidays.None)
    {
        query = query.Include(e => e.Holidays);

        switch (includeHoliday)
        {
            case IncludeHolidays.Future:
                query = query.Where(e => e.Holidays.Where(h => h.Date >= DateTime.UtcNow));
                break;
            case IncludeHolidays.Past:
                query = query.Where(e => e.Holidays.Where(h => h.Date < DateTime.UtcNow));
                break;
        }
    }

    return query.FirstOrDefault();
}

由于嵌套的

Where
调用,上述方法无法编译。但是,我不能使用
Holidays.Any
Holidays.Any
,因为如果员工没有符合该条件的假期,这些将排除员工。

如何查询假期而不影响已识别的员工?

实现我想要做的事情的 SQL 查询示例可能是:

select * from "Employees" e 
left join "Holidays" h on e."Id" = h."EmployeeId" and h."Date" >= current_timestamp
where e."Id" = 'employee_id';
c# entity-framework-core npgsql ef-core-8.0
2个回答
0
投票

你搞砸了

Where
Include
。这是两件事,
Include
是加载相关实体的指令,EF Core 添加了过滤这些相关实体的可能性。

更正您的查询:

Employee? GetEmployee(Guid employeeId, IncludeHolidays includeHolidays)
{
    var query = ctx.Employees
        .Where(e => e.Id == employee.Id)
        .AsQueryable();

    if (includeHoliday != IncludeHolidays.None)
    {
        switch (includeHoliday)
        {
            case IncludeHolidays.Future:
                query = query.Include(e => e.Holidays.Where(h => h.Date >= DateTime.UtcNow));
                break;
            case IncludeHolidays.Past:
                query = query.Include(e => e.Holidays.Where(h => h.Date < DateTime.UtcNow));
                break;
        }
    }

    return query.FirstOrDefault();
}

0
投票

您可以将条件语句传递到包含中,在这种情况下,您可以执行如下代码片段所示的操作:

query = query.Include(e => e.Holidays.Where(x => includeHoliday != IncludeHolidays.None && (includeHoliday == IncludeHolidays.All || (includeHoliday == IncludeHolidays.Past ? x.Date < DateTime.UtcNow : x.Date >= DateTime.UtcNow))));

这也允许您删除下面的行。

© www.soinside.com 2019 - 2024. All rights reserved.