Ich migriere einige Dinge von einem MySQL-Server auf einen SQL-Server, aber ich kann nicht herausfinden, wie dieser Code funktioniert:
using (var context = new Context())
{
...
foreach (var item in collection)
{
IQueryable<entity> pages = from p in context.pages
where p.Serial == item.Key.ToString()
select p;
foreach (var page in pages)
{
DataManager.AddPageToDocument(page, item.Value);
}
}
Console.WriteLine("Done!");
Console.Read();
}
Wenn es in die Sekunde eintritt, wird foreach (var page in pages)
eine Ausnahme ausgelöst, die besagt:
LINQ to Entities erkennt die Methode 'System.String ToString ()' nicht und diese Methode kann nicht in einen Speicherausdruck übersetzt werden.
Weiß jemand warum das passiert?
Antworten:
Speichern Sie die Zeichenfolge einfach in einer temporären Variablen und verwenden Sie diese in Ihrem Ausdruck:
Das Problem tritt auf, weil
ToString()
es nicht wirklich ausgeführt wird, sondern in eine MethodGroup umgewandelt und dann analysiert und in SQL übersetzt wird. Da es keinToString()
Äquivalent gibt, schlägt der Ausdruck fehl.Hinweis:
Stellen Sie sicher, dass Sie auch Alex 'Antwort bezüglich der
SqlFunctions
später hinzugefügten Hilfsklasse lesen . In vielen Fällen kann die Notwendigkeit der temporären Variablen entfallen.quelle
ToString()
keine davon.ExecuteQuery
oder mithilfe von Entity SQL mitObjectQuery<T>
Wie andere geantwortet haben, bricht dies ab, da .ToString auf dem Weg in die Datenbank nicht in relevantes SQL übersetzt werden kann.
Microsoft stellt jedoch die SqlFunctions-Klasse bereit , eine Sammlung von Methoden, die in solchen Situationen verwendet werden können.
In diesem Fall suchen Sie hier nach SqlFunctions.StringConvert :
Gut, wenn die Lösung mit temporären Variablen aus irgendeinem Grund nicht wünschenswert ist.
Ähnlich wie bei SqlFunctions haben Sie auch die EntityFunctions (mit EF6, die von DbFunctions veraltet sind ), die einen anderen Satz von Funktionen bereitstellen, die auch datenquellenunabhängig sind (nicht beschränkt auf z. B. SQL).
quelle
Das Problem ist, dass Sie ToString in einer LINQ to Entities-Abfrage aufrufen. Das bedeutet, dass der Parser versucht, den ToString-Aufruf in das entsprechende SQL zu konvertieren (was nicht möglich ist ... daher die Ausnahme).
Sie müssen lediglich den ToString-Aufruf in eine separate Zeile verschieben:
quelle
Hatte ein ähnliches Problem. Es wurde behoben, indem ToList () für die Entitätssammlung aufgerufen und die Liste abgefragt wurde. Wenn die Sammlung klein ist, ist dies eine Option.
Hoffe das hilft.
quelle
Ändern Sie es so und es sollte funktionieren:
Der Grund, warum die Ausnahme nicht in der Zeile ausgelöst wird, in der die LINQ-Abfrage deklariert ist, sondern in der Zeile der
foreach
Funktion, ist die verzögerte Ausführung, dh die LINQ-Abfrage wird erst ausgeführt, wenn Sie versuchen, auf das Ergebnis zuzugreifen. Und das passiert imforeach
und nicht früher.quelle
Cast table to
Enumerable
, dann rufen Sie LINQ-Methoden mit using-ToString()
Methode auf:Seien Sie jedoch vorsichtig, wenn Sie
AsEnumerable
oderToList
Methoden aufrufen , da Sie vor dieser Methode alle Daten von allen Entitäten anfordern. In meinem obigen Fall habe ich alletable_name
Zeilen nach einer Anfrage gelesen .quelle
Das Upgrade auf Entity Framework Version 6.2.0 hat bei mir funktioniert.
Ich war vorher auf Version 6.0.0.
Hoffe das hilft,
quelle
Nehmen Sie in MVC an, dass Sie Datensätze basierend auf Ihren Anforderungen oder Informationen suchen. Es funktioniert richtig.
quelle
Wenn Sie
ToString
Ihre Abfrage wirklich eingeben möchten , können Sie einen Besucher des Ausdrucksbaums schreiben, der den AufrufToString
mit einem Aufruf der entsprechendenStringConvert
Funktion neu schreibt :quelle
First
hier ist, auf deren ErgebnisseGetMethods()
zurückgegeben wirdMethodInfo[]
. AFAIKMethodInfo[]
hat weder eineFind
Methode noch eine solche Erweiterungsmethode. Aber ich sollte es wirklich verwenden,Single
da diese Methode über Reflection gefunden wird und es keinen Fehler bei der Kompilierung gibt, wenn die entsprechende Methode nicht behoben werden kann.Ich habe in diesem Fall den gleichen Fehler erhalten:
Nachdem ich viel zu viel Zeit mit dem Debuggen verbracht hatte, stellte ich fest, dass der logische Ausdruck einen Fehler aufwies.
Die erste Zeile
search.Contains(log.Id.ToString())
funktioniert einwandfrei, aber die letzte Zeile, die sich mit einem DateTime-Objekt befasst, hat dazu geführt, dass es kläglich fehlgeschlagen ist:Entfernen Sie die problematische Linie und das Problem ist gelöst.
Ich verstehe nicht ganz warum, aber es scheint, dass ToString () ein LINQ-Ausdruck für Zeichenfolgen ist, aber nicht für Entitäten. LINQ for Entities behandelt Datenbankabfragen wie SQL, und SQL kennt ToString () nicht. Daher können wir ToString () nicht in eine .Where () -Klausel werfen.
Aber wie funktioniert dann die erste Zeile? Anstelle von ToString () hat SQL
CAST
undCONVERT
, daher gehe ich bisher davon aus, dass linq for entity dies in einigen einfachen Fällen verwendet. DateTime-Objekte sind nicht immer so einfach ...quelle
Verwandeln Sie die LINQ to Entity-Abfrage einfach in eine LINQ to Objects-Abfrage (z. B. ToArray aufrufen), wenn Sie einen Methodenaufruf in Ihrer LINQ-Abfrage verwenden müssen.
quelle