EF Core 2.1 RC 1 GroupBy все еще оценивает локально - PullRequest
0 голосов
/ 16 мая 2018

Я обновил проект ASP.NET Core с версии 2.0.x до 2.1.0-rc1 , следуя официальному руководству из блога ASP.NET,Пакеты EF Core также были обновлены до той же версии.Поставщик базы данных, который я использую: Microsoft.EntityFrameworkCore.SqlServer .Я ждал этого обновления с предвкушением, так как мне очень нужна была функция LINQ GroupBy для перевода .Один из моих запросов следующий:

await _db.Documents
         .ApplyFilter(options)
         .Where(x => x.SubscriptionId == subscriptionId && x.Status != DocumentStatus.Deleted)
         .GroupBy(document => new { document.SubscriptionId })
         .Select(group => new {
            Total = group.Sum(x => x.Total),
            TotalDiscount = group.Sum(x => x.TotalDiscount),
            TotalNet = group.Sum(x => x.TotalNet != null ? x.TotalNet.Value * (decimal)x.CurrencyRate : 0),
            SubTotal = group.Sum(x => x.SubTotal != null ? x.SubTotal.Value * (decimal)x.CurrencyRate : 0),
            TotalSalesTax = group.Sum(x => x.TotalSalesTax != null ? x.TotalSalesTax.Value * (decimal)x.CurrencyRate : 0),
            TotalTax = group.Sum(x => x.TotalTax != null ? x.TotalTax.Value * (decimal)x.CurrencyRate : 0),
            TotalPayable = group.Sum(x => x.TotalPayable != null ? x.TotalPayable.Value * (decimal)x.CurrencyRate : 0)
        })
        .ToListAsync();

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

EFCore Linq Query Не удалось перевести и будет оцениваться локально.

Итак, я хотел бы спросить, не делаю ли я что-то (ужасно) неправильно или эта функция еще не доступна, поскольку она рекламируется?Кто-нибудь из вас пробовал что-то подобное?Заранее благодарю за помощь.


Редактировать

Для того, чтобы встряхнуть тестирование, проблема пробовала следующий запрос (убрал условные проверки из метода Sum) как Иван Стоев предложил в комментариях, но результат тот же.

await _db.Documents
         .ApplyFilter(options)
         .Where(x => x.SubscriptionId == subscriptionId && x.Status != DocumentStatus.Deleted)
         .GroupBy(document => new { document.SubscriptionId })
         .Select(group => new {
            Total = group.Sum(x => x.Total),
            TotalDiscount = group.Sum(x => x.TotalDiscount),
            TotalNet = group.Sum(x => x.TotalNet),
            SubTotal = group.Sum(x => x.SubTotal),
            TotalSalesTax = group.Sum(x => x.TotalSalesTax),
            TotalTax = group.Sum(x => x.TotalTax),
            TotalPayable = group.Sum(x => x.TotalPayable)
          })
          .ToListAsync();

Решение

После экспериментов я понял следующее.Я публикую это на тот случай, если у кого-то возникнет такая же проблемаСледующий запрос прекрасно переведен в оператор T-SQL и, следовательно, не выполняется на клиенте.

await (from d in _db.Documents.ApplyFilter(options)
       where d.SubscriptionId == subscriptionId && d.Status != DocumentStatus.Deleted
       group d by d.SubscriptionId into g
       select new {
          Total = g.Sum(x => x.Total/* * Convert.ToDecimal(x.CurrencyRate)*/),
          TotalDiscount = g.Sum(x => x.TotalDiscount/* * Convert.ToDecimal(x.CurrencyRate)*/),
          TotalNet = g.Sum(x => x.TotalNet/* * Convert.ToDecimal(x.CurrencyRate)*/),
          SubTotal = g.Sum(x => x.SubTotal/* * Convert.ToDecimal(x.CurrencyRate)*/),
          TotalSalesTax = g.Sum(x => x.TotalSalesTax/* * Convert.ToDecimal(x.CurrencyRate)*/),
          TotalTax = g.Sum(x => x.TotalTax/* * Convert.ToDecimal(x.CurrencyRate)*/),
          TotalPayable = g.Sum(x => x.TotalPayable/* * Convert.ToDecimal(x.CurrencyRate)*/)
       }).ToListAsync();

Очевидное отличие состоит в том, что вместо * используется синтаксис LINQ .1041 * методы расширения .Также я прокомментировал умножение со свойством CurrencyRate как , что также приводит к локальной оценке запроса .Это кажется довольно странным, поскольку синтаксис запроса также переводится в методы расширения под капотом.

Я также открыл проблему в Github-репозитории Entity Framework Core, которую вы можете найти здесь

Ответы [ 2 ]

0 голосов
/ 23 апреля 2019

В моем случае группировка была оценена на стороне клиента для этого запроса:

await context.MyCollection
.GroupBy(x => x.Tag.Id)
.ToDictionaryAsync(x => x.Key, x => x.Count());

Изменение его на приведенное ниже сделало оценку на стороне сервера:

await context.MyCollection
.GroupBy(x => x.Tag.Id)
.Select(g => new {g.Key, Count = g.Count()})
.ToDictionaryAsync(arg => arg.Key, arg => arg.Count);
0 голосов
/ 16 мая 2018

GroupBy - это красная сельдь.

Использование синтаксиса запроса компилируется до использования методов расширения, так что это не проблема.

Единственное отличие, которое я вижу между версией вВаше редактирование и версия в синтаксисе запроса заключается в том, что вы делаете _db.Documents.ApplyFilter(...) в тех случаях, когда группирование по-прежнему оценивается локально.Я предполагаю, что это приводит к смещению возвращаемого типа к чему-то другому и выбору неправильных перегрузок, или к некоторым подобным деталям, которые приводят в замешательство переводчик запросов - это приведет к всем операторам LINQ (где, Select, GroupBy и т. Д.), Которые будут оцениваться локально.

...