Atualmente, estou aprimorando o LINQ e tentando compreender a diferença entre let
e usando a into
palavra - chave. Até agora, a let
palavra - chave parece melhor do que a into
palavra - chave, pelo que entendi.
A into
palavra-chave permite essencialmente continuar uma consulta após uma projeção. (Só quero declarar explicitamente que não estou me referindo àquele para entrar em grupo.)
Dado um conjunto de nomes, permite fazer o seguinte:
var intoQuery =
from n in names
select Regex.Replace(n, "[aeiou]", "")
into noVowel
where noVowel.Length > 2
select noVowel;
Leva o resultado do select e coloca-o na noVowel
variável que permite então que a introduzir adicionais where
, orderby
e select
cláusulas. Depois que a noVowel
variável é criada, ela n
não está mais disponível.
A let
palavra-chave, por outro lado, usa tipos anônimos temporários para permitir que você reutilize mais de uma variável por vez.
Você pode fazer o seguinte:
var letQuery =
from n in names
let noVowel = Regex.Replace(n, "[aeiou]", "")
where noVowel.Length > 2
select noVowel;
As variáveis noVowel
e n
estão disponíveis para uso (embora eu não tenha usado neste caso).
Embora eu possa ver a diferença, não consigo entender por que alguém iria querer usar a into
palavra-chave em vez da palavra- let
chave, a menos que alguém quisesse explicitamente ter certeza de que as variáveis anteriores não puderam ser usadas nas últimas partes da consulta.
Então, há um bom motivo para as duas palavras-chave existirem?
let
exemplo - owhere noVowel
que énoVowel
nesse caso?Respostas:
Sim, porque estão fazendo coisas diferentes, como você disse.
select ... into
isola efetivamente toda uma consulta e permite que você a use como entrada para uma nova consulta. Pessoalmente, geralmente prefiro fazer isso por meio de duas variáveis:var tmp = from n in names select Regex.Replace(n, "[aeiou]", ""); var noVowels = from noVowel in tmp where noVowel.Length > 2 select noVowel;
(É certo que, neste caso, faria isso com a notação de ponto em duas linhas, mas ignorando isso ...)
Freqüentemente, você não quer toda a bagagem da parte anterior da consulta - que é quando você usa
select ... into
ou divide a consulta em duas, conforme o exemplo acima. Isso não apenas significa que as partes anteriores da consulta não podem ser usadas quando não deveriam, mas simplifica o que está acontecendo - e é claro que significa que há potencialmente menos cópias em cada etapa.Por outro lado, quando você não quiser manter o resto do contexto,
let
faz mais sentido.fonte
A principal diferença é que
let
injeta a variável no contexto / escopo, ondeinto
cria um novo contexto / escopo.fonte
Querendo saber a diferença no lado do banco de dados, escreveu 2 consultas do Entity Framework.
Deixei
from u in Users let noVowel = u.FirstName.Replace("a","").Replace("e","").Replace("i","") where noVowel.Length >5 select new {u.FirstName, noVowel}
Para dentro
from u in Users select u.FirstName.Replace("a","").Replace("e","").Replace("i","") into noVowel where noVowel.Length >5 select noVowel
Os SQLs gerados são quase idênticos . O SQL não é perfeito, o mesmo código de processo de string é repetido em 2 lugares (onde e selecione).
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
Aqui está o SQL gerado pelo 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
Parece que o Linq-to-SQL é mais inteligente do que o Entity Framework, processo de string executado apenas uma vez.
fonte
Versão visualizada da resposta de leppie . Como pode ser visto, o compilador produz erro na consulta ao
into
contrário da última no acesso à primeira variável.fonte