Как я могу написать запрос Linq, который возвращает строки, относящиеся к определенному периоду дат?

Я использую EF Core 7 и C#. В модели у одного Employee есть много Periods и много Tickets.

У меня есть следующие классы:

public class Employee
{    
    public string EmployeeId { get; set; }    
    public string FullName { get; set; }

    public List<Period> Periods { get; set; }
    public List<Ticket> Tickets { get; set; }
}

public class Period
{
    public int PeriodId { get; set; }  
    
    public DateTime From { get; set; }
    public DateTime To { get; set; }
    
    public Employee Employee { get; set; }
    public string EmployeeId { get; set; } //FK pointing to Employee
}

public class Ticket
{ 
    public string TicketId { get; set; }        
    
    public DateTime CreationDate { get; set; }
   
    public string EmployeeId { get; set; } //FK pointing to Employee
}

Как я могу написать запрос linq, который возвращает билеты, находящиеся в диапазон периода сотрудников? Мне нужен результат в виде IQueryable<Ticket>.

Вот запрос, который я пытался:

// I create a list of employees Id's
var employeeIds = new List<string> { "9854", "4587", "2587" };

IQueryable<Ticket> result =
     from ticket in DbContext.Tickets
     where employeeIds.Contains(ticket.EmployeeId) &&
     
           // Here I need to set the condition for tickets
           // that are inside the Period of each employee
           // [Period.From , Period.To] 
     
     select ticket;
}

(1) Стоимость вашего билета CreationDate — это старые даты или дата/время? (2) Являются ли значения даты периода To включенными в дату (00:00 последнего включенного дня) или исключительными датами (00:00 следующего дня)? -- Это существенно влияет на то, как вам нужно сравнивать даты с диапазонами дат.

T N 25.08.2024 04:42

Действительно приятно видеть, что кто-то не забыл включить определение класса csharp в свой вопрос!

rachel 25.08.2024 07:07
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
2
97
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это должно быть то, что вы хотите:

IQueryable<Ticket> result = 
     from ticket in DbContext.Tickets
      where employeeIds.Contains(ticket.EmployeeId)  
        && DbContext.Periods.Any(p => p.EmployeeId == ticket.EmployeeId 
            && ticket.CreationDate >= p.From && ticket.CreationDate <= p.To)
    select ticket;

Поэтому я проверяю, есть ли хотя бы один период для каждого сотрудника билета, который от/до находится в диапазоне CreationDate билета.

Если вас устраивает результат IEnumerable<Ticket> вместо IQueryable<Ticket>, вы также можете выполнить объединение идентификаторов сотрудников, заявок и периодов по идентификаторам сотрудников. а затем отфильтровать билеты по периодам «До/От».

    //I create a list of employees Id's
    var employeeIds = new List<string> {"9854", "4587", "2587"};
    var tickets = new List<Ticket>
    {
        new Ticket {TicketId = "ticketId1", EmployeeId = "9854", CreationDate = new DateTime(2021, 9, 20)},
        new Ticket {TicketId = "ticketId2", EmployeeId = "9854", CreationDate = new DateTime(2021, 10, 20)},
        new Ticket {TicketId = "ticketId3", EmployeeId = "9855", CreationDate = new DateTime(2021, 9, 20)},
    };

    var periods = new List<Period>
    {
        new Period {PeriodId = 1, EmployeeId = "9854", From = new DateTime(2021, 8, 20), To = new DateTime(2021, 9, 21)},
        new Period {PeriodId = 2, EmployeeId = "9854", From = new DateTime(2021, 10, 18), To = new DateTime(2021, 10, 21)},
    };

    var results = (from employeedId in employeeIds
        join period in periods on employeedId equals period.EmployeeId into employeePeriods
        join ticket in tickets on employeedId equals ticket.EmployeeId into employeeTickets
        where employeeTickets.Count() > 0 && employeePeriods.Count() > 0
        select new {employeePeriods, employeeTickets}).SelectMany(q =>
    {
        var employeeTickets = q.employeeTickets;
        var employeePeriods = q.employeePeriods;
        var ticketsWithinPeriod = employeeTickets.Where(t => employeePeriods.Any(p => p.From <= t.CreationDate && p.To >= t.CreationDate));
        return ticketsWithinPeriod;
    });

Результаты:

Другие вопросы по теме