У меня есть 2 таблицы, одна с городами, а другая со значениями температуры/даты для городов, город может иметь несколько дат с температурой.

Как я мог с помощью EF + linq привести города + самую последнюю температуру каждого из них

Что-то вроде: _context.city.include(x=> x.temperature().last());

2
Rene Figueroa Blasquez 3 Фев 2022 в 23:02
Пожалуйста, всегда используйте тег, указывающий точную версию EF, потому что это очень важно для ответа на вопрос.
 – 
Gert Arnold
3 Фев 2022 в 23:40

3 ответа

Вы можете добиться этого, спроецировав город и последнюю температуру на новый объект в выражении Select. Во фрагменте кода, который вы включили в свой вопрос, отсутствует несколько шагов, поэтому я собираюсь предположить ваши структуры данных:

await _context.Cities.Select(city => new
{
    City = city,
    LastTemperature = city.Temperatures
                         .OrderByDescending(t => t.DateRecorded)
                         .FirstOrDefault(),
}).ToListAsync();
1
Andrew Williamson 3 Фев 2022 в 23:39

Вы всегда должны контролировать, какая температура является «последней», упорядочивая их по выбранному свойству. При этом имеет смысл использовать Take(1) в Include, например, чтобы получить самый последний:

_context.Cities
    .Include(x=> x.Temperatures.OrderByDescending(t => t.Date).Take(1));

Отфильтрованный/упорядоченный Include поддерживается начиная с ядра EF 5< /а>.

Поскольку вы уже пытаетесь что-то сделать в этом направлении, я предполагаю, что вы используете EFC 5 или 6.

1
Gert Arnold 3 Фев 2022 в 23:54

Я не сторонник фильтрации включений, поскольку это приводит к двусмысленности (свойство nav отфильтрованного включения считается loaded, поэтому пользователь результата должен знать о возможном инкапсулированном поведении). Я бы предпочел проецировать на новый/анонимный тип:

_context.TemperatureReading
    .GroupBy( tr => tr.City )
    .Select( g => new
    {
        City = g.Key,
        LatestTemp = g.OrderByDescending( t => t.Date ).First(),
    } );
1
Moho 4 Фев 2022 в 00:08