Spędziłem ostatnie 6 miesięcy walcząc z tym ograniczeniem z EF 3.5 i chociaż nie jestem najmądrzejszą osobą na świecie, jestem prawie pewien, że mam coś przydatnego do zaoferowania na ten temat.
SQL wygenerowany przez wyrośnięcie drzewa o wysokości 50 mil wyrażenia "OR style" spowoduje słaby plan wykonania kwerendy. Mam do czynienia z kilkoma milionami wierszy, a wpływ jest znaczny.
Jest trochę Hack znalazłem zrobić SQL „w”, który pomaga, jeśli tylko szukasz grono podmiotów przez ID:
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 jest podstawowy klucz nazwa kolumny id Twój stół Entity1.
ALE PRZECZYTAJ CZYTANIE!
To jest w porządku, ale wymaga to posiadania identyfikatorów tego, co muszę znaleźć. Czasami po prostu chcę, by moje wyrażenia sięgały do innych relacji, a to, co mam, to kryteria dla tych powiązanych relacji.
Gdybym miał więcej czasu, spróbowałbym przedstawić to wizualnie, ale nie zastanawiam się przez chwilę nad tym zdaniem: Zastanów się nad schematem za pomocą tabel Person, GovernmentId i GovernmentIdType. Andrew Tappert (osoba) ma dwie karty id (GovernmentId), jedną z Oregon (GovernmentIdType) i jedną z Washington (GovernmentIdType).
Teraz wygeneruj edmx z niego.
Teraz wyobraź sobie, że chcesz znaleźć wszystkie osoby posiadające pewną wartość identyfikatora, powiedzmy 1234567.
Można to osiągnąć z jednej bazy danych uderzony z tym:
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);
widzisz podzapytanie tutaj? Wygenerowany sql użyje "sprzężeń" zamiast pod-zapytań, ale efekt jest taki sam. Obecnie serwer SQL optymalizuje podkwerendy do złączeń pod pokrywami, ale tak czy inaczej ...
Kluczem do tego działania jest. Any wewnątrz wyrażenia.
Dzięki Daniel. Ta sama składnia działa dobrze na zwykłym Linq. Wygląda na to, że problem tkwi w EF w .Net 3.5 SP1, prawda? Zawartość bez nawiasu jest równoważna z: gdzie upperSearchList.All (x => (person.FirstName + person.LastName) .Contains (x)). ToList(); –
Jeśli spróbuję gdzie upperSearchList.All (arg => arg == arg), zgłasza ten sam błąd. Problem z metodą All ... –
LINQ to Entities to wspaniała technologia, ale silnik do tłumaczenia SQL jest ograniczony. Nie mogę położyć ręki na oficjalnej dokumentacji, ale z mojego doświadczenia wynika, że jeśli zapytanie zawiera więcej niż tylko podstawowe funkcje matematyczne i łańcuchowe/daty, to nie zadziała. Czy miałeś okazję sprawdzić, który post został połączony? Opisuje proces konwertowania zapytania typu "WHERE..IN" do postaci, którą LINQ do Entities można następnie przetłumaczyć na SQL. –