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 mir ziemlich sicher, dass ich zu diesem Thema etwas Nützliches zu bieten habe.
Die SQL, die durch das Wachsen eines 50 Meilen hohen Baums von Ausdrücken im "OR-Stil" generiert wird, führt zu einem schlechten Ausführungsplan für Abfragen. Ich habe es mit ein paar Millionen Zeilen zu tun und die Auswirkungen sind erheblich.
Es gibt einen kleinen Hack, den ich gefunden habe, um ein SQL-In auszuführen, das hilft, wenn Sie nur nach einer Reihe von Entitäten anhand der 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 + "}");
}
Dabei ist pkIDColumn der Name Ihrer Primärschlüssel-ID-Spalte in Ihrer Entity1-Tabelle.
ABER LESEN SIE WEITER!
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 lang: Betrachten Sie ein Schema mit den Tabellen Person, GovernmentId und GovernmentIdType. Andrew Tappert (Person) hat zwei ID-Karten (GovernmentId), eine aus Oregon (GovernmentIdType) und eine aus Washington (GovernmentIdType).
Generieren Sie nun einen edmx daraus.
Stellen Sie sich nun vor, Sie möchten alle Personen mit einem bestimmten ID-Wert finden, z. B. 1234567.
Dies kann mit einem einzigen Datenbanktreffer 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);
Sehen Sie die Unterabfrage hier? Die generierte SQL verwendet 'Joins' anstelle von Unterabfragen, aber der Effekt ist der gleiche. Heutzutage optimiert SQL Server Unterabfragen ohnehin in Joins unter dem Deckmantel, aber trotzdem ...
Der Schlüssel zu dieser Arbeit ist das .Any im Ausdruck.