EF Core groupBy no SQL перевод для нуль-сливающегося оператора (??). ISNULL не используется для перевода при выполнении ?? 0m - PullRequest
0 голосов
/ 09 января 2020

Использование EF Core 2.2 с

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

Рабочий запрос groupBy linq к sql серверной базе данных не может быть выполнен на стороне сервера из-за изменения Select(t=>t.Value) на Select(t=>t.Value??0m).

Почему он не переводится в SQL, поскольку может стать SUM (ISNULL (Value, 0))?

Я знаю, что в этом нет необходимости, но я хотел бы понять, как это работает под капотом я чувствую, что что-то упустил.

1 Ответ

1 голос
/ 09 января 2020

Это EF Core 2.2 GroupBy дефект / ограничение транслятора запросов (уже исправленный в EF Core 3.x), который не поддерживает выражения методов агрегирования, отличные от простого доступа к "свойству".

Временное решение: использовать промежуточную проекцию (анонимного типа), содержащую все необходимые выражения (чтобы они стали «свойствами»), используя перегрузку GroupBy с селектором элемента.

Например, для данной сущности, подобной этой:

public class SomeEntity
{
    public int Id { get; set; }
    public int SomeKey { get; set; }
    public decimal? SomeValue { get; set; }
}

и желаемый, но неудачный запрос EFC2.2, подобный следующему:

var query = db.Set<SomeEntity>()
    .GroupBy(e => e.SomeKey)
    .Select(g => new
    {
        g.Key,
        Value = g.Sum(e => e.SomeValue ?? 0m) // <--
    });

модифицированное рабочее решение EFC2.2 может выглядеть следующим образом:

var query = db.Set<SomeEntity>()
    .GroupBy(e => e.SomeKey, e => new { SomeValue = e.SomeValue ?? 0m }) // <--
    .Select(g => new
    {
        g.Key,
        Value = g.Sum(e => e.SomeValue) // <--
    });

Более общее решение, хотя это просто переместить нулевой оператор объединения из агрегатной функции:

var query = db.Set<SomeEntity>()
    .GroupBy(e => e.SomeKey)
    .Select(g => new
    {
        g.Key,
        Value = g.Sum(e => e.SomeValue) ?? 0m // <--
    });
...