Как отсортировать запрос LINQ / Entity Framework по свойству внука - PullRequest
1 голос
/ 25 сентября 2019

У меня проблема с запросом LINQ.У меня есть следующая структура данных (классы Entity Framework, сопоставленные с базой данных SQL Server):

Событие имеет свойство EventBlocks с 0 или более объектами EventBlock в качестве дочерних.EventBlock имеет свойство Details с 0 или более объектами EventBlockDetail в качестве дочерних.EventBlockDetail имеет DetailDate и StartTime.

Мне нужно показать следующие 3 предстоящих события на веб-сайте.Порядок сортировки определяется самой ранней датой и временем начала события, которая хранится в Event -> EventBlock -> EventBlockDetail.Если следующие 2 или 3 предстоящих события EventBlockDetails принадлежат одному и тому же событию, это событие должно отображаться только один раз, а другое событие должно отображаться в верхних 3.

Есть ли способ выполнить это с помощьюодин запрос LINQ, поэтому мне не нужно будет делать много циклов и сравнивать после получения ВСЕХ данных о событиях из базы данных?

Чтобы проиллюстрировать, что я пытаюсь сделать, вот фиктивный запрос, которыйочевидно, не будет работать, потому что первый OrderBy не знает, какое свойство для заказа.

var result = this.Context.Events.Where(
    e => e.WebsiteId == websiteId && 
        e.EventBlocks.All(
            b => b.Details.All(
                d => d.DetailDate >= DateTime.Now
            )
        )
    ).OrderBy( 
        e => e.EventBlocks.OrderBy(
            b => eb.Details.Min(d => d.DetailDate)).ThenBy(
            b => eb.Details.Min(d => d.StartTime))
    ).Take(nrOfEvents).ToList();

1 Ответ

1 голос
/ 25 сентября 2019

Вы должны быть в состоянии выбрать событие и самую раннюю дату и время, упорядочив все детали события по дате и времени и выбрав первое.Затем вы можете использовать эту деталь для фильтрации и упорядочения событий.

var result = Context.Events
    .Where(e => e.WebsiteId == websiteId)
    .Select(e => new 
    { 
        Event = e, 
        StartDetails = e.EventBlocks
            .SelectMany(b => b.Details)
            .OrderBy(d => d.DetailDate) 
            .ThenBy(d => d.StartTime)
            .FirstOrDefault()
    })
    .Where(x => x.StartDetails.DetailDate >= DateTime.Now)
    .OrderBy(x => x.StartDetails.DetailDate)
    .ThenBy(x => x.StartDetails.StartTime)
    .Take(nrOfEvents)
    .Select(x => x.Event)
    .ToList();

Обратите внимание, что фильтр x => x.StartDetails.DetailDate >= DateTime.Now может удалить что-то, что еще не запущено, если DetailDate урезает время.В этом случае вы можете захотеть отфильтровать по DateTime.Today, но также отфильтровать, если время раньше текущего, если дата сегодня.Например, если деталь имеет дату 2019-09-25 (предположительно, сохраненную со временем полуночи), то сравнение с 2019-09-25 в 8:00 (если это текущее время даты) не удастся, даже если время начала детализациипосле 8 часов утрасмысл и быть более простым запросом, если дата и время хранятся в одном столбце вместо двух.

...