EF Core 3.1 выбрать First() из Group

Есть удаленный MSSQLServer, на котором есть довольно "тяжелая" View, которую я хочу обработать на стороне сервера БД и не тащить на клиент лишние данные.

Написал запрос, который, по идее, должен вытянуть на клиент только первые значения из каждой группы по полю TAG_NAME, каждая группа в свою очередь отсортирована по дате createDate:

  var tParams = context.TechSet
        .Where(x => x.createDate < endDate && x.createDate > startDate)
        .OrderByDescending(d => d.createDate)
        .GroupBy(x=>x.TAG_NAME)
        .Select(z=>z.First())
        .ToList();

Получаю длинный Exception, основная суть которого следующая:

   ...First()' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList()...

Как правильно написать запрос, чтобы он смог корректно транслироваться в SQL ?


Ответы (1 шт):

Автор решения: Exodium

После некоторого изучения форумов пришел к выводу, что разработчики EFCore 3.0/3.1 перепроектировали LINQ провайдер и на дату задания вопроса данный фреймворк не умеет транслировать GroupBy на сторону SQL. Это весьма не очевидный факт и возможно этот оператор когда-то войдет в список транслируемых.

Также удалось найти решение, которое можно применить к моей ситуации. Основано на применении подзапроса IQueryable<T>:

var subquery = context.TechSet.Select(x => new { Key = x.TAG_NAME, Tech = x });

var parameters = 
subquery.Select(x => x.Key).Distinct().SelectMany(key => 
                            subquery.Where(e => e.Key == key)
                              .Select(e => e.Tech)
                              .Where(t => t.createDate < endDate && t.createDate > startDate)
                              .OrderByDescending(m => m.createDate)
                              .Take(1)).ToList();

Даже при использовании подзапроса скорость выполнения выросла в 4 раза по сравнению с Where на стороне БД и (GroupBy() + First()) на стороне клиента.

→ Ссылка