Spędziłem ostatnie 6 miesięcy walcząc z tym ograniczeniem za pomocą EF 3.5 i chociaż nie jestem najmądrzejszą osobą na świecie, jestem prawie pewien, że mam coś pożytecznego do zaoferowania na ten temat.
Kod SQL wygenerowany przez powiększenie drzewa wyrażeń „w stylu OR” o wysokości 50 mil spowoduje słaby plan wykonania zapytania. Mam do czynienia z kilkoma milionami wierszy, a wpływ jest znaczący.
Znalazłem mały hack dotyczący wykonywania kodu SQL `` in '', który pomaga, jeśli szukasz tylko kilku jednostek według identyfikatora:
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 + "}");
}
gdzie pkIDColumn to nazwa kolumny identyfikatora klucza podstawowego tabeli Entity1.
ALE CZYTAJCIE!
To jest w porządku, ale wymaga posiadania już identyfikatorów tego, co muszę znaleźć. Czasami po prostu chcę, aby moje wyrażenia sięgały do innych relacji, a to, co mam, to kryteria tych powiązanych relacji.
Gdybym miał więcej czasu, spróbuję przedstawić to wizualnie, ale nie przestudiuję tego zdania przez chwilę: rozważ schemat z tabelami Person, GovernmentId i GovernmentIdType. Andrew Tappert (osoba) ma dwie karty identyfikacyjne (GovernmentId), jedną z Oregonu (GovernmentIdType) i jedną z Waszyngtonu (GovernmentIdType).
Teraz wygeneruj z niego edmx.
Teraz wyobraź sobie, że chcesz znaleźć wszystkie osoby o określonej wartości identyfikacyjnej, powiedzmy 1234567.
Można to osiągnąć za pomocą pojedynczego trafienia w bazie danych w ten sposób:
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);
Czy widzisz tutaj podzapytanie? Wygenerowany sql użyje „złączeń” zamiast pod-zapytań, ale efekt jest taki sam. W dzisiejszych czasach serwer SQL i tak optymalizuje podzapytania pod kątem łączenia pod osłonami, ale i tak ...
Kluczem do tej pracy jest .Any wewnątrz wyrażenia.