LINQ To Entities не распознает метод Last.В самом деле? - PullRequest
134 голосов
/ 03 сентября 2011

В этом запросе:

public static IEnumerable<IServerOnlineCharacter> GetUpdated()
{
    var context = DataContext.GetDataContext();
    return context.ServerOnlineCharacters
        .OrderBy(p => p.ServerStatus.ServerDateTime)
        .GroupBy(p => p.RawName)
        .Select(p => p.Last());
}

Я должен был переключить его на это, чтобы он работал

public static IEnumerable<IServerOnlineCharacter> GetUpdated()
{
    var context = DataContext.GetDataContext();
    return context.ServerOnlineCharacters
        .OrderByDescending(p => p.ServerStatus.ServerDateTime)
        .GroupBy(p => p.RawName)
        .Select(p => p.FirstOrDefault());
}

Я даже не мог использовать p.First(), чтобы отразить первый запрос.

Почему существуют такие основные ограничения в том, что в противном случае является такой надежной системой ORM?

Ответы [ 6 ]

204 голосов
/ 03 сентября 2011

Это ограничение сводится к тому, что в конечном итоге он должен перевести этот запрос в SQL , а SQL имеет SELECT TOP (в T-SQL), но не SELECT BOTTOM (такого нет).

Хотя есть простой способ обойти это, просто убавить порядок и затем сделать First(), что вы и сделали.

РЕДАКТИРОВАТЬ: Другие поставщики, возможно, будут иметь различные реализации SELECT TOP 1, в Oracle это может быть что-то более похожее на WHERE ROWNUM = 1

РЕДАКТИРОВАТЬ:

Еще один менее эффективныйальтернатива - Я НЕ РЕКОМЕНДУЮ! - это вызов .ToList() для ваших данных до .Last(), который немедленно выполнит выражение LINQ To Entities, которое было построено до этого момента, а затем ваш.Last () будет работать, потому что в этот момент .Last() эффективно выполняется в контексте выражения LINQ to Objects .(И, как вы указали, это может привести к тысячам записей и бесполезной загрузке материализационных объектов ЦП, которые никогда не будут использоваться)

Опять же, я бы не советовал делать эту секунду, но это помогает проиллюстрировать разницумежду где и когда выполняется выражение LINQ.

31 голосов
/ 25 августа 2016

Вместо Last(), попробуйте это:

model.OrderByDescending(o => o.Id).FirstOrDefault();
14 голосов
/ 23 августа 2013

Замените Last() селектором Linq OrderByDescending(x => x.ID).Take(1).Single()

Нечто подобное будет работать, если вы предпочитаете делать это в Linq:

public static IEnumerable<IServerOnlineCharacter> GetUpdated()
{
    var context = DataContext.GetDataContext();
    return context.ServerOnlineCharacters.OrderBy(p => p.ServerStatus.ServerDateTime).GroupBy(p => p.RawName).Select(p => p.OrderByDescending(x => x.Id).Take(1).Single());
}
0 голосов
/ 17 июня 2019

Добавление одной функции AsEnumerable() до того, как функция выбора работала для меня.
Пример:

return context.ServerOnlineCharacters
    .OrderByDescending(p => p.ServerStatus.ServerDateTime)
    .GroupBy(p => p.RawName).AsEnumerable()
    .Select(p => p.FirstOrDefault());

Ref: https://www.codeproject.com/Questions/1005274/LINQ-to-Entities-does-not-recognize-the-method-Sys

0 голосов
/ 30 января 2019

Это потому, что LINQ to Entities (и базы данных в целом) не поддерживает все методы LINQ (подробности см. Здесь: http://msdn.microsoft.com/en-us/library/bb738550.aspx)

Здесь вам нужно упорядочить данные таким образом, чтобы «последняя» запись стала «первой», а затем вы можете использовать FirstOrDefault. Обратите внимание, что базы данных обычно не имеют таких понятий, как «первый» и «последний», это не значит, что последняя добавленная запись будет «последней» в таблице.

Этот метод может решить вашу проблему

db.databaseTable.OrderByDescending(obj => obj.Id).FirstOrDefault();
0 голосов
/ 21 июля 2017

Еще один способ получить последний элемент без OrderByDescending и загрузить все сущности:

dbSet
    .Where(f => f.Id == dbSet.Max(f2 => f2.Id))
    .FirstOrDefault();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...