In dieser Abfrage:
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());
}
Ich musste es darauf umstellen, damit es funktionierte
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());
}
Ich konnte nicht einmal verwenden p.First()
, um die erste Abfrage zu spiegeln.
Warum gibt es so grundlegende Einschränkungen bei einem ansonsten so robusten ORM-System?
c#
entity-framework
orm
bevacqua
quelle
quelle
Antworten:
Diese Einschränkung beruht auf der Tatsache, dass diese Abfrage schließlich in SQL übersetzt werden muss und SQL eine
SELECT TOP
(in T-SQL), aber keineSELECT BOTTOM
(keine solche) hat.Es gibt jedoch einen einfachen Weg, einfach absteigend zu bestellen und dann ein zu machen
First()
, was Sie getan haben.BEARBEITEN: Andere Anbieter haben möglicherweise andere Implementierungen von
SELECT TOP 1
, unter Oracle wäre es wahrscheinlich eher soWHERE ROWNUM = 1
BEARBEITEN:
Eine andere weniger effiziente Alternative - ich empfehle dies NICHT! - müssen Sie
.ToList()
Ihre Daten vorher aufrufen.Last()
, wodurch sofort der bis zu diesem Punkt erstellte LINQ To Entities-Ausdruck ausgeführt wird, und dann funktioniert Ihre .Last (), da zu diesem Zeitpunkt die.Last()
im Kontext von a effektiv ausgeführt wird LINQ to Objects Expression stattdessen. (Und wie Sie bereits betont haben, könnte dies Tausende von Datensätzen zurückbringen und eine Menge CPU-materialisierender Objekte verschwenden, die niemals verwendet werden.)Auch hier würde ich nicht empfehlen, diese Sekunde auszuführen, aber es hilft, den Unterschied zwischen dem Ort und dem Zeitpunkt der Ausführung des LINQ-Ausdrucks zu veranschaulichen.
quelle
ToList
ist das Anrufen nicht so schlecht.Last()
Versuchen Sie stattdessen Folgendes:quelle
Last()
Durch einen Linq-Selektor ersetzenOrderByDescending(x => x.ID).Take(1).Single()
So etwas würde funktionieren, wenn Sie es in Linq vorziehen:
quelle
Noch eine andere Möglichkeit, das letzte Element ohne OrderByDescending abzurufen und alle Entitäten zu laden:
quelle
Dies liegt daran, dass LINQ to Entities (und Datenbanken im Allgemeinen) nicht alle LINQ-Methoden unterstützt (Einzelheiten finden Sie hier: http://msdn.microsoft.com/en-us/library/bb738550.aspx ).
Was Sie hier brauchen, ist, Ihre Daten so zu ordnen, dass der "letzte" Datensatz "zuerst" wird und Sie dann FirstOrDefault verwenden können. Beachten Sie, dass Datenbanken normalerweise keine Konzepte wie "first" und "last" haben. Es ist nicht so, dass der zuletzt eingefügte Datensatz "last" in der Tabelle ist.
Diese Methode kann Ihr Problem lösen
quelle
Das Hinzufügen einer einzelnen Funktion
AsEnumerable()
vor der Auswahlfunktion hat bei mir funktioniert.Beispiel:
Ref: https://www.codeproject.com/Questions/1005274/LINQ-to-Entities-does-not-recognize-the-method-Sys
quelle