Piszę sporo linq w moim codziennym życiu, ale przeważnie są to proste stwierdzenia. Zauważyłem, że używając klauzul where, istnieje wiele sposobów ich zapisywania i każdy z nich daje takie same wyniki, o ile wiem. Na przykład;
from x in Collection
where x.Age == 10
where x.Name == "Fido"
where x.Fat == true
select x;
Wydaje się to równoważne przynajmniej w zakresie wyników:
from x in Collection
where x.Age == 10 &&
x.Name == "Fido" &&
x.Fat == true
select x;
Czy naprawdę istnieje różnica inna niż składnia? Jeśli tak, jaki jest preferowany styl i dlaczego?
EDYCJA: LINQ to Objects nie zachowuje się tak, jak się spodziewałem. Być może zainteresuje Cię wpis na blogu , który właśnie o tym napisałem ...
Różnią się tym, co zostanie nazwane - pierwszy jest odpowiednikiem:
Collection.Where(x => x.Age == 10) .Where(x => x.Name == "Fido") .Where(x => x.Fat == true)
gdzie to ostatnie jest równoważne z:
Collection.Where(x => x.Age == 10 && x.Name == "Fido" && x.Fat == true)
Teraz, jaka to faktycznie różnica, zależy od implementacji metody
Where
call. Jeśli jest to dostawca oparty na języku SQL, spodziewałbym się, że w końcu utworzą ten sam SQL. Jeśli znajduje się w LINQ to Objects, druga będzie miała mniej poziomów pośrednich (będą zaangażowane tylko dwie iteratory zamiast czterech). To, czy te poziomy pośrednictwa są istotne z punktu widzenia szybkości, to inna sprawa.Zwykle
where
użyłbym kilku klauzul, jeśli czuję, że reprezentują one znacząco różne warunki (np. Jedna dotyczy jednej części obiektu, a druga jest całkowicie oddzielna) i jednejwhere
klauzuli, gdy różne warunki są ściśle powiązane (np. Określona wartość jest większe niż minimum i mniejsze niż maksimum). Zasadniczo warto rozważyć czytelność przed jakąkolwiek drobną różnicą wydajności.źródło
Pierwsza z nich zostanie wdrożona:
Collection.Where(x => x.Age == 10) .Where(x => x.Name == "Fido") // applied to the result of the previous .Where(x => x.Fat == true) // applied to the result of the previous
W przeciwieństwie do znacznie prostszego (i prawdopodobnie
znacznieszybszego):// all in one fell swoop Collection.Where(x => x.Age == 10 && x.Name == "Fido" && x.Fat == true)
źródło
kiedy biegnę
from c in Customers where c.CustomerID == 1 where c.CustomerID == 2 where c.CustomerID == 3 select c
i
from c in Customers where c.CustomerID == 1 && c.CustomerID == 2 && c.CustomerID == 3 select c customer table in linqpad
w mojej tabeli Customer wyświetla to samo zapytanie sql
-- Region Parameters DECLARE @p0 Int = 1 DECLARE @p1 Int = 2 DECLARE @p2 Int = 3 -- EndRegion SELECT [t0].[CustomerID], [t0].[CustomerName] FROM [Customers] AS [t0] WHERE ([t0].[CustomerID] = @p0) AND ([t0].[CustomerID] = @p1) AND ([t0].[CustomerID] = @p2)
więc w tłumaczeniu na sql nie ma różnicy i już widzieliście w innych odpowiedziach jak zostaną one przekonwertowane na wyrażenia lambda
źródło
Patrząc pod maskę, te dwie instrukcje zostaną przekształcone w różne reprezentacje zapytań. W zależności od
QueryProvider
oCollection
, to może być zoptymalizowane z dala lub nie.Gdy jest to wywołanie linq-to-object, wiele klauzul where prowadzi do łańcucha IEnumerables, które odczytują się od siebie. Użycie formularza z jedną klauzulą pomoże w tym przypadku.
Gdy dostawca bazowy przetłumaczy to na instrukcję SQL, istnieje duże prawdopodobieństwo, że oba warianty utworzą tę samą instrukcję.
źródło