Nesta consulta:
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());
}
Eu tive que mudar isso para isso funcionar
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());
}
Eu não conseguia nem usar p.First()
, para espelhar a primeira consulta.
Por que existem limitações básicas no que é de outra forma um sistema ORM tão robusto?
c#
entity-framework
orm
bevacqua
fonte
fonte
Respostas:
Essa limitação se resume ao fato de que, eventualmente, ela deve converter essa consulta para SQL e o SQL possui um
SELECT TOP
(em T-SQL), mas não umSELECT BOTTOM
(não existe).Existe uma maneira fácil de contornar isso, basta ordenar a descida e depois fazer a
First()
, que foi o que você fez.EDIT: Outros provedores possivelmente terão implementações diferentes de
SELECT TOP 1
, no Oracle provavelmente seria algo mais parecidoWHERE ROWNUM = 1
EDITAR:
Outra alternativa menos eficiente - eu não recomendo isso! - é chamar
.ToList()
seus dados antes.Last()
, o que executará imediatamente a expressão LINQ To Entities que foi criada até esse ponto e, em seguida, o seu .Last () funcionará, porque nesse momento ele.Last()
é efetivamente executado no contexto de um LINQ to Expressão de Objetos . (E como você apontou, isso pode trazer de volta milhares de registros e desperdiçar cargas de objetos de materialização da CPU que nunca serão usados)Novamente, eu não recomendaria fazer isso segundo, mas ajuda a ilustrar a diferença entre onde e quando a expressão LINQ é executada.
fonte
ToList
não é tão ruim.Em vez de
Last()
, tente o seguinte:fonte
Substitua
Last()
por um seletor LinqOrderByDescending(x => x.ID).Take(1).Single()
Algo assim seria bom se você preferir fazê-lo no Linq:
fonte
Outra maneira de obter o último elemento sem OrderByDescending e carregar todas as entidades:
fonte
Isso ocorre porque o LINQ to Entities (e bancos de dados em geral) não oferece suporte a todos os métodos LINQ (consulte aqui para obter detalhes: http://msdn.microsoft.com/en-us/library/bb738550.aspx )
O que você precisa aqui é solicitar seus dados de forma que o "último" registro se torne "primeiro" e, em seguida, você possa usar o FirstOrDefault. Observe que o banco de dados geralmente não possui conceitos como "primeiro" e "último", não é como se o registro inserido mais recentemente fosse "último" na tabela.
Este método pode resolver seu problema
fonte
Adicionar uma única função
AsEnumerable()
antes da função Selecionar funcionou para mim.Exemplo:
Ref: https://www.codeproject.com/Questions/1005274/LINQ-to-Entities-does-not-recognize-the-method-Sys
fonte