Скорее всего, этот запрос LINQ также не может быть переведен в EF Core 2.2 из-за некоторых ограничений, которые имеет оператор GroupBy
.
Из документов:
Поскольку никакая структура базы данных не может представлять IGrouping, операторы GroupBy в большинстве случаев не имеют перевода. Когда к каждой группе применяется агрегатный оператор, который возвращает скаляр, его можно преобразовать в SQL GROUP BY в реляционных базах данных. SQL GROUP BY также является ограничительным. Это требует от вас группировки только по скалярным значениям. Прогноз может содержать только ключевые столбцы группировки или любой агрегат, примененный к столбцу.
В EF Core 2.x произошло то, что всякий раз, когда он не мог преобразовать выражение, он автоматически переключался на оценку клиента и выдавал только предупреждение.
Это указано как критическое изменение, оказывающее наибольшее влияние при переходе на EF Core› = 3.x:
Старое поведение
До версии 3.0, когда EF Core не мог преобразовать выражение, являющееся частью запроса, в SQL или в параметр, оно автоматически вычисляло выражение на клиенте. По умолчанию при оценке потенциально дорогостоящих выражений клиентом выдается только предупреждение.
Новое поведение
Начиная с версии 3.0, EF Core позволяет оценивать на клиенте только выражения в проекции верхнего уровня (последний вызов Select () в запросе). Если выражения в любой другой части запроса не могут быть преобразованы ни в SQL, ни в параметр, создается исключение.
Поэтому, если производительность этого выражения была достаточно хорошей при использовании EF Core 2.x, она будет такой же хорошей, как и раньше, если вы решите явно переключиться на оценку клиента при использовании EF Core 5.x. Это потому, что оба оцениваются клиентом, раньше и сейчас, с той лишь разницей, что вы должны прямо сейчас заявить об этом. Таким образом, простой выход, если производительность ранее была приемлемой, - это просто оценить клиентом последнюю часть запроса, используя .AsEnumerable()
или .ToList()
.
Если производительность оценки клиента неприемлема (что будет означать, что этого не было и до миграции), вам необходимо переписать запрос. Есть пара ответов Ивана Стоева, которые могут вас вдохновить.
Меня немного смущает описание того, чего вы хотите достичь: I need to find the products with unique title for a particular category
и опубликованный вами код, поскольку я считаю, что он не выполняет то, что вы объяснили. В любом случае я предоставлю возможные решения для обеих интерпретаций.
Это моя попытка написать запрос to find the products with unique title for a particular category
.
var uniqueProductTitlesForCategoryQueryable = currentContext.Products
.Where(x => x.CategoryId == categoryId)
.GroupBy(x => x.Title)
.Where(x => x.Count() == 1)
.Select(x => x.Key); // Key being the title
var productsWithUniqueTitleForCategory = currentContext.Products
.Where(x => x.CategoryId == categoryId)
.Where(x => uniqueProductTitlesForCategoryQueryable .Contains(x.Title))
.Select(x => new ProductViewModel
{
Id = x.Id,
Title = x.Title,
CategoryId= x.CategoryId
}).ToList();
И это моя попытка переписать отправленный вами запрос:
currentContext.Products
.Select(product => product.Title)
.Distinct()
.SelectMany(uniqueTitle => currentContext.Products.Where(product => product.Title == uniqueTitle ).Take(1))
.Select(product => new ProductViewModel
{
Id = product.Id,
Title = product.Title,
CategoryId= product.CategoryId
})
.ToList();
Я получаю различные заголовки в таблице Product
, и для каждого отдельного заголовка я получаю первый Product
, который ему соответствует (это должно быть эквивалентно GroupBy(x => x.Title)
+ FirstOrDefault
AFAIK). При необходимости вы можете добавить сортировку перед Take(1)
.
person
dglozano
schedule
28.03.2021
FirstOrDefault
большеGroupBy
не поддерживается. Так что либо воспользуйтесь советом по переключению оценки клиента (поскольку ваш запрос действительно оценивался клиентом до EFC 3.0), либо обратитесь к SO, чтобы переписать запрос - есть много похожих вопросов, поскольку это обычная проблема. - person Ivan Stoev   schedule 17.03.2021Title
не уникален. Это не кажется здоровым условием дляProduct
стола. - person Gert Arnold   schedule 17.03.2021AsEnumerable()
передGroupBy
. Если раньше тебе было все равно, то почему сейчас? (2) Как я писал в предыдущем комментарии, так называемые Top N элементов для каждой группы очень распространены, но не обрабатываются EFC, поэтому их много раз спрашивали и отвечали, что вы бы нашли, если бы искали SO, как было предложено. Я могу легко приспособиться к вашему случаю и дать один из моих собственных ответов, но это не имеет смысла - вопрос просто дурацкий. - person Ivan Stoev   schedule 24.03.2021