Obecnie odświerzam LINQ i próbuję zrozumieć różnicę między let
i używając into
słowa kluczowego. Jak dotąd let
słowo kluczowe wydaje się lepsze niż into
słowo kluczowe, o ile wiem.
Słowo into
kluczowe zasadniczo umożliwia kontynuowanie zapytania po projekcji. (Chcę tylko wyraźnie powiedzieć, że nie odnoszę się do tego, który służy do dołączania do grupy).
Biorąc pod uwagę tablicę nazw, można wykonać następujące czynności:
var intoQuery =
from n in names
select Regex.Replace(n, "[aeiou]", "")
into noVowel
where noVowel.Length > 2
select noVowel;
Zajmuje wynik select i umieszcza ją w noVowel
zmiennej, która następnie pozwala na wprowadzenie dodatkowych where
, orderby
oraz select
klauzule. Po noVowel
utworzeniu n
zmiennej nie jest już dostępna.
Z let
drugiej strony słowo kluczowe używa tymczasowych typów anonimowych, aby umożliwić ponowne użycie więcej niż jednej zmiennej naraz.
Możesz wykonać następujące czynności:
var letQuery =
from n in names
let noVowel = Regex.Replace(n, "[aeiou]", "")
where noVowel.Length > 2
select noVowel;
Dostępne są zarówno zmienne, jak noVowel
i n
(mimo że nie używałem ich w tym przypadku).
Chociaż widzę różnicę, nie bardzo rozumiem, dlaczego ktoś miałby chcieć użyć into
słowa kluczowego zamiast słowa let
kluczowego, chyba że wyraźnie chciałoby się upewnić, że poprzednie zmienne nie mogą być używane w późniejszych częściach zapytania.
Czy jest więc dobry powód, dla którego istnieją oba słowa kluczowe?
let
przykład literówka -where noVowel
conoVowel
w takim razie jest?Odpowiedzi:
Tak, ponieważ robią różne rzeczy, jak powiedziałeś.
select ... into
skutecznie izoluje całość jednego zapytania i umożliwia użycie go jako danych wejściowych do nowego zapytania. Osobiście zazwyczaj wolę to robić za pomocą dwóch zmiennych:var tmp = from n in names select Regex.Replace(n, "[aeiou]", ""); var noVowels = from noVowel in tmp where noVowel.Length > 2 select noVowel;
(Co prawda w tym przypadku zrobiłbym to z notacją kropkową w dwóch wierszach, ale ignorując to ...)
Często nie chcesz całego bagażu z wcześniejszej części zapytania - czyli gdy używasz
select ... into
lub dzielisz zapytanie na dwie części, jak w powyższym przykładzie. Nie tylko oznacza to, że wcześniejsze części zapytania nie mogą być używane, gdy nie powinny, ale także upraszcza to, co się dzieje - i oczywiście oznacza, że na każdym kroku odbywa się potencjalnie mniej kopiowania.Z drugiej strony, jeśli nie chcesz zachować resztę kontekście
let
większy sens.źródło
Podstawową różnicą jest
let
wstrzyknięcie zmiennej do kontekstu / zakresu, gdzieinto
tworzy nowy kontekst / zakres.źródło
Chcąc poznać różnicę po stronie bazy danych, napisał 2 zapytania Entity Framework.
Pozwolić
from u in Users let noVowel = u.FirstName.Replace("a","").Replace("e","").Replace("i","") where noVowel.Length >5 select new {u.FirstName, noVowel}
W
from u in Users select u.FirstName.Replace("a","").Replace("e","").Replace("i","") into noVowel where noVowel.Length >5 select noVowel
Wygenerowane SQL są prawie identyczne . SQL nie jest doskonały, ten sam łańcuchowy kod procesu jest powtarzany w 2 miejscach (gdzie i wybierz).
SELECT 1 AS [C1], [Extent1].[FirstName] AS [FirstName], REPLACE(REPLACE(REPLACE([Extent1].[FirstName], N'a', N''), N'e', N''), N'i', N'') AS [C2] FROM [dbo].[User] AS [Extent1] WHERE ( CAST(LEN(REPLACE(REPLACE(REPLACE([Extent1].[FirstName], N'a', N''), N'e', N''), N'i', N'')) AS int)) > 5 GO SELECT REPLACE(REPLACE(REPLACE([Extent1].[FirstName], N'a', N''), N'e', N''), N'i', N'') AS [C1] FROM [dbo].[User] AS [Extent1] WHERE ( CAST(LEN(REPLACE(REPLACE(REPLACE([Extent1].[FirstName], N'a', N''), N'e', N''), N'i', N'')) AS int)) > 5
Oto kod SQL wygenerowany przez LINQ-to-SQL
-- Region Parameters DECLARE @p0 NVarChar(1000) = 'a' DECLARE @p1 NVarChar(1000) = '' DECLARE @p2 NVarChar(1000) = 'e' DECLARE @p3 NVarChar(1000) = '' DECLARE @p4 NVarChar(1000) = 'i' DECLARE @p5 NVarChar(1000) = '' DECLARE @p6 Int = 5 -- EndRegion SELECT [t1].[FirstName], [t1].[value] AS [noVowel] FROM ( SELECT [t0].[FirstName], REPLACE(REPLACE(REPLACE([t0].[FirstName], @p0, @p1), @p2, @p3), @p4, @p5) AS [value] FROM [User] AS [t0] ) AS [t1] WHERE LEN([t1].[value]) > @p6 GO -- Region Parameters DECLARE @p0 NVarChar(1000) = 'a' DECLARE @p1 NVarChar(1000) = '' DECLARE @p2 NVarChar(1000) = 'e' DECLARE @p3 NVarChar(1000) = '' DECLARE @p4 NVarChar(1000) = 'i' DECLARE @p5 NVarChar(1000) = '' DECLARE @p6 Int = 5 -- EndRegion SELECT [t1].[value] FROM ( SELECT REPLACE(REPLACE(REPLACE([t0].[FirstName], @p0, @p1), @p2, @p3), @p4, @p5) AS [value] FROM [User] AS [t0] ) AS [t1] WHERE LEN([t1].[value]) > @p6
Wydaje się, że Linq-to-SQL jest inteligentniejsze niż Entity Framework, proces tworzenia ciągu znaków jest wykonywany tylko raz.
źródło
Wizualizowana wersja odpowiedzi leppiego . Jak widać, kompilator zwraca błąd w zapytaniu, w
into
odróżnieniu od drugiego, jako dostęp do pierwszej zmiennej.źródło