O LINQ To Entities não reconhece o método Last. Mesmo?

Nesta consulta:

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

Eu tive que mudar isso para isso funcionar

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

Eu não poderia nem usar p.First() , para espelhar a primeira consulta.

Por que existem tais limitações básicas no que é um sistema ORM tão robusto?

Essa limitação se resume ao fato de que, eventualmente, ela precisa traduzir essa consulta para SQL e SQL tem um SELECT TOP (em T-SQL), mas não um SELECT BOTTOM (nada disso).

Existe uma maneira fácil de contornar isso, apenas faça a ordem decrescente e então faça um First() , que é o que você fez.

EDIT: Outros provedores possivelmente terão diferentes implementações do SELECT TOP 1 , no Oracle provavelmente seria algo mais como WHERE ROWNUM = 1

EDITAR:

Outra alternativa menos eficiente – eu não recomendo isso! – é chamar .ToList() em seus dados antes de .Last() , que imediatamente executará o LINQ To Entities Expression que foi construído até aquele ponto, e então seu .Last () funcionará, porque nesse ponto o .Last() é efetivamente executado no contexto de um LINQ to Objects Expression. (E como você apontou, isso pode trazer de volta milhares de registros e desperdiçar cargas de CPU materializando objects que nunca serão usados)

Novamente, eu não recomendaria fazer este segundo, mas ajuda a ilustrar a diferença entre onde e quando a expressão LINQ é executada.

Em vez de Last() , tente isto:

 model.OrderByDescending(o => o.Id).FirstOrDefault(); 

Substitua Last() por um seletor Linq OrderByDescending(x => x.ID).Take(1).Single()

Algo assim seria trabalhoso se você preferir fazer isso no Linq:

 public static IEnumerable 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()); } 

Ainda outra maneira obter último elemento sem OrderByDescending e carregar todas as entidades:

 dbSet .Where(f => f.Id == dbSet.Max(f2 => f2.Id)) .FirstOrDefault();