Ich habe die letzten 6 Monate damit verbracht, diese Einschränkung mit EF 3.5 zu bekämpfen und obwohl ich nicht die klügste Person der Welt bin, bin ich ziemlich sicher, dass ich etwas Nützliches zu diesem Thema zu bieten habe.
Die SQL, die generiert wird, indem ein 50 Meilen hoher Baum von "OR-Stil" -Ausdrücken wächst, führt zu einem schlechten Abfrageausführungsplan. Ich habe es mit ein paar Millionen Zeilen zu tun und die Auswirkungen sind beträchtlich.
Es gibt einen kleinen Hack, den ich ‚in‘ eine SQL zu tun gefunden, das hilft, wenn Sie nur für eine Reihe von Einrichtungen, die von id suchen:
private IEnumerable<Entity1> getByIds(IEnumerable<int> ids)
{
string idList = string.Join(",", ids.ToList().ConvertAll<string>(id => id.ToString()).ToArray());
return dbContext.Entity1.Where("it.pkIDColumn IN {" + idList + "}");
}
wo pkIDColumn ist Ihre primären Schlüssel-ID Spalt Namen Ihre Entity1-Tabelle.
ABER LESEN!
Das ist in Ordnung, aber es erfordert, dass ich bereits die IDs von dem habe, was ich finden muss. Manchmal möchte ich nur, dass meine Ausdrücke in andere Beziehungen hineinreichen und was ich habe, sind Kriterien für diese verbundenen Beziehungen.
Wenn ich mehr Zeit hätte, würde ich versuchen, dies visuell darzustellen, aber ich studiere diesen Satz nicht nur einen Moment: Betrachten Sie ein Schema mit einer Person, GovernmentId und GovernmentIdType-Tabellen. Andrew Tappert (Person) hat zwei ID-Karten (GovernmentId), eine aus Oregon (GovernmentIdType) und eine aus Washington (GovernmentIdType).
Jetzt generieren Sie eine EDMX daraus.
Nun stellen Sie alle Leute finden, wollen einen bestimmten ID-Wert, sagt 1234567.
Dies kann mit einer einzigen Datenbank mit diesem Hit erreicht werden:
dbContext context = new dbContext();
string idValue = "1234567";
Expression<Func<Person,bool>> expr =
person => person.GovernmentID.Any(gid => gid.gi_value.Contains(idValue));
IEnumerable<Person> people = context.Person.AsQueryable().Where(expr);
Haben Sie die Unterabfrage zu sehen Hier? Das generierte sql verwendet 'Joins' anstelle von Unterabfragen, aber der Effekt ist der gleiche. Heutzutage optimiert SQL Server Unterabfragen in Joins unter den Abdeckungen sowieso, aber trotzdem ...
Der Schlüssel zu dieser Arbeit ist die .Any innerhalb des Ausdrucks.
Danke Daniel. Die gleiche Syntax funktioniert gut mit Linq. Also, es sieht nach Problem ist mit EF in. NET 3.5 SP1 richtig? Das Enthält ohne Klammern entspricht: wo obereSuchliste.Alle (x => (person.FirstName + person.LastName). Enthält (x)). ToList(); –
Wenn ich versuche, wo upperSearchList.All (arg => arg == arg) es den gleichen Fehler wirft. So ist das Problem mit der All-Methode ... –
LINQ to Entities ist eine wunderbare Technologie, aber die SQL-Übersetzungs-Engine ist begrenzt. Ich kann nicht die offizielle Dokumentation in die Hände bekommen, aber nach meiner Erfahrung wird es nicht funktionieren, wenn die Abfrage mehr als nur einfache Mathematik- und String/Date-Funktionen enthält. Hattest du die Chance, den Beitrag zu lesen, den ich verlinkt habe? Es beschreibt einen Prozess zum Umwandeln einer Abfrage vom Typ "WHERE..IN" in ein Formular, das LINQ to Entities dann in SQL übersetzen kann. –