EF Core 3.1 Сумма принадлежащих свойств объекта не работает - PullRequest
0 голосов
/ 09 июля 2020

Он работал в 2.1, но начал давать сбой на 3.1

System.InvalidCastException: 'Unable to cast object of type 'System.Linq.Expressions.NewExpression' to type 'System.Linq.Expressions.MethodCallExpression'.'
var ordersCounts = await ordersCountsQuery 
       .Select(x => new TransactionDTO
       {
            Value = new MoneyDTO(ordersCountsQuery.Sum(a => a.TotalPrice.Amount)) // worked perfectly on 2.1
       })
       .FirstOrDefaultAsync();

a.TotalPrice.Amount это decimal на Sql базе данных сервера

В EF Core 2.1 я установил это вверх

.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning))

1 Ответ

0 голосов
/ 09 июля 2020

Похоже, вы можете столкнуться с этим критическим изменением между версиями структуры сущностей 2.2 и 3.0:

https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#linq -запросы-больше-не-оцениваются-на- client

Старое поведение

До версии 3.0, когда EF Core не мог преобразовать выражение, которое было частью запроса, в SQL или параметр, оно автоматически оценил выражение на клиенте. По умолчанию клиентская оценка потенциально дорогостоящих выражений вызывает только предупреждение.

Новое поведение

Начиная с версии 3.0, EF Core допускает выражения только в проекции верхнего уровня (последний вызов Select () в запросе) для оценки на клиенте. Когда выражения в любой другой части запроса не могут быть преобразованы ни в SQL, ни в параметр, выдается исключение.

В этом случае вам придется заново напишите свой запрос в соответствии с требованиями (это может быть два отдельных запроса).

Замечу, что ваш запрос выглядит немного странно структурированным:

var ordersCounts = await ordersCountsQuery 
   .Select(x => new TransactionDTO
   {
        Value = new MoneyDTO(ordersCountsQuery.Sum(a => a.TotalPrice.Amount)) // worked perfectly on 2.1
   })
   .FirstOrDefaultAsync();

Получите список MoneyDTO (по одному для каждого элемента в запросе), каждый из которых содержит сумму общего списка и выберите первый.

Следующее будет делать то же самое и, вероятно, будет немного более производительным (возвращает только одно значение:

var totalPrice = ordersCountsQuery.Sum(a => a.TotalPrice.Amount);

var orderCounts = new TransactionDTO
{
    Value = new MoneyDTO(totalPrice) 
};
...