Okay, oto oferta: dataContext.Table1s
jest typu IQueryable<T>
. IQueryable<T>
definiuje metody Where
i Any
, które pobierają predykat typu Expression<Func<T, bool>>
. Okładka Expression<>
ma kluczowe znaczenie, ponieważ pozwala LINQ na SQL na przetłumaczenie wyrażenia lambda na SQL i wykonanie go na serwerze bazy danych.
Jednak IQueryable<T>
zawiera także IEnumerable<T>
. IEnumerable<T>
również definiuje metody Where
i Any
, ale wersja IEnumerable przyjmuje predykat typu Func<T, bool>
. Ponieważ jest to funkcja skompilowana, a nie wyrażenie, nie można jej przetłumaczyć na SQL. W wyniku tego kodu ...
Func<Table1, bool> lambda = x => x.Id > 1000;
var result = dataContext.Table1s.Where(lambda);
... będzie ciągnąć każdy rekord z Table1s
do pamięci, a następnie filtrować rekordy w pamięci. Działa, ale to naprawdę zła wiadomość, jeśli twój stół jest duży.
Func<Table1, bool> lambda = x => x.Id > 1000;
var result = dataContext.Table2s.Where(x => x.Table1s.Any(lambda));
Ta wersja ma dwa wyrażenia lambda. Drugi, przekazywany bezpośrednio do Where
, to Expression
, który zawiera odniesienie do Func
. Nie można ich mieszać, a komunikat o błędzie, który otrzymujesz, mówi, że wywołanie Any
oczekuje Expression
, ale przechodzisz pod numer Func
.
var result = dataContext.Table2s.Where(x => x.Table1s.Any(y => y.Id > 1000));
W tej wersji, twój wewnętrzny lambda jest automatycznie przekształcane do Expression
bo to jedyny wybór, jeśli chcesz, aby Twój kod zostać przekształcona SQL przez LINQ to SQL. W innych przypadkach wymuszasz na lambmie Func
zamiast na Expression
- w tym przypadku nie jesteś, więc to działa.
Jakie jest rozwiązanie? Jest to całkiem proste:
Expression<Func<Table1, bool>> lambda = x => x.Id > 1000;
Spróbuj użyć 'var lamda = x => x.Id> 1000;'. Nie wiem, czy to pomoże, ale może ... – Alxandr
@Alxandr - to nie jest legalne. Wyrażenia lambdy mogą być kompilowane do 'Func <>' lub 'Expression>' iw twoim przykładzie kompilator nie będzie mógł powiedzieć, który z nich chcesz i spowoduje błąd. –