В чем заключается проблема с оценкой сервера, вызывающая сбой этого запроса EF Core 3.1? - PullRequest
2 голосов
/ 23 января 2020

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

Это запрос

using (var ctx = new GsContext())
{
    var recs = ctx.Calibrations
                  .Where(ca => ca.DeviceId == deviceId)
                  .AsNoTracking()
                  .Include(c => c.Cartridge)
                  .OrderByDescending(i => i.CalibratedOn)
                  .GroupBy(r => r.CartridgeId)
                  .Select(q => q.First())
                  .ToList();

Я не вижу, чтобы я делал какие-либо сложные проекции или что-либо, что требовало бы оценки на стороне клиента перед выбором, поэтому сообщение об исключении меня смущает. Это был текст сообщения об ошибке:

Выражение LINQ '(GroupByShaperExpression: KeySelector: (c .CartridgeId), ElementSelector: (EntityShaperExpression: EntityType: Значение калибровкиBufferExpression: (ProjectionBindingExp:: ProjectionBindingExp: IsNullable: False)). Первая () не может быть переведена. Либо переписать запрос в форме, которую можно перевести, либо явно переключиться на оценку клиента, вставив вызов либо AsEnumerable (), AsAsyncEnumerable (), ToList (), либо ToListAsyn c (). См. https://go.microsoft.com/fwlink/?linkid=2101038 для получения дополнительной информации.

Я уже сталкивался с такими исключениями, как раньше, когда мои запросы пытались выполнить некоторую сложную обработку строк в начале запроса ( Как я уже сказал, я узнал об этой проблеме трудным путем), но это не тот случай, по крайней мере, не то, что я вижу.

Я нашел этот связанный вопрос , но в этом случае парень делал прогноз в рамках предложения GroupBy. Я этого не делаю.

Если это поможет, вот класс калибровки

public class Calibration
{
    [Key]
    [Required]
    public int      Id                 { get; set; }

    [Required]
    public int      DeviceId           { get; set; }

    [Required]
    public int      CartridgeId        { get; set; }

    [ForeignKey(nameof(CartridgeId))]
    public Cartridge Cartridge          { get; set; }

    public DateTime CalibratedOn     { get; set; }
}

Я уверен, что смогу обойти это. Я прошу лучше понять оценку клиент / сервер. Может кто-нибудь объяснить мне, что мне не хватает? Что касается моего запроса, требуется оценка клиента

1 Ответ

2 голосов
/ 24 января 2020

Я нашел этот связанный вопрос , но в этом случае парень делал проекцию в предложении GroupBy. Я не делаю этого.

Ну, вот в чем проблема, в моем ответе связанного поста, который я написал:

К сожалению, в настоящее время EF Core 3.0 / 3.1 поддерживает только серверный перевод GroupBy с проекцией ключа / агрегатов (аналогично SQL).

Другими словами, вы должен иметь проекцию, содержащую только ключ и / или агрегаты после GroupBy, иначе он не будет переводиться.

Здесь относится к проблеме GitHub. И некоторые пояснения из официальных документов по Сложные операторы запросов - GroupBy :

Операторы LINQ GroupBy создают результат типа IGrouping<TKey, TElement>, где TKey и TElement может быть любым произвольным типом. Кроме того, IGrouping реализует IEnumerable<TElement>, что означает, что вы можете создавать поверх него любой оператор LINQ после группировки. Поскольку ни одна структура базы данных не может представлять IGrouping, операторы GroupBy в большинстве случаев не имеют перевода. Когда оператор агрегирования применяется к каждой группе, которая возвращает скаляр, его можно преобразовать в SQL GROUP BY в реляционных базах данных. SQL GROUP BY также является ограничительным. Требуется группировка только по скалярным значениям. Проекция может содержать только ключевые столбцы группировки или любой агрегат, примененный к столбцу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...