2009-03-13 14 views
84

Actualmente estoy revisando LINQ y estoy tratando de comprender la diferencia entre let y usando la palabra clave into. Hasta ahora, la palabra clave let parece mejor que la palabra clave into, según mi comprensión. La palabra clave into esencialmente permite continuar una consulta después de una proyección. (Sólo quiero indicar explícitamente que no me refiero a la otra para unirse a grupo.)¿La palabra clave let de linq es mejor que su palabra clave?

Dada una matriz de nombres que permite a uno hacer lo siguiente:

var intoQuery = 
    from n in names 
    select Regex.Replace(n, "[aeiou]", "") 
    into noVowel 
    where noVowel.Length > 2 
    select noVowel; 

Se toma el resultado de la seleccione y lo coloca en la variable noVowel, que luego permite introducir cláusulas where, orderby y select adicionales. Una vez que se crea la variable noVowel, la variable n ya no está disponible.

La palabra clave let, por otro lado, utiliza tipos temporales anónimos para permitirle reutilizar más de una variable a la vez.

Usted puede hacer lo siguiente:

var letQuery = 
    from n in names 
    let noVowel = Regex.Replace(n, "[aeiou]", "") 
    where noVowel.Length > 2 
    select noVowel; 

Tanto las variables noVowel y n están disponibles para su uso (aunque yo no lo he utilizado en este caso).

Aunque puedo ver la diferencia, no puedo entender por qué uno querría usar la palabra clave into sobre la palabra clave let a menos que se quiera asegurarse explícitamente de que las variables anteriores no se puedan usar en las últimas partes de la consulta.

Entonces, ¿hay una buena razón por la cual ambas palabras clave existen?

+0

¿Es un error tipográfico en el ejemplo 'let' -' where noVowel', ¿qué es 'noVowel' en ese caso? – sll

Respuesta

82

Sí, porque están haciendo cosas diferentes, como dices.

select ... into aísla efectivamente la totalidad de una consulta y le permite usarla como entrada para una nueva consulta. Personalmente por lo general prefiero hacerlo a través de dos variables:

var tmp = from n in names 
      select Regex.Replace(n, "[aeiou]", ""); 

var noVowels = from noVowel in tmp 
       where noVowel.Length > 2 
       select noVowel; 

(Es cierto que en este caso lo haría con la notación de punto en dos líneas, pero haciendo caso omiso de que ...)

A menudo don 't quiere todo el equipaje de la parte anterior de la consulta, que es cuando usa select ... into o divide la consulta en dos según el ejemplo anterior. Esto no solo significa que las partes anteriores de la consulta no se pueden usar cuando no deberían, sino que simplifica lo que está sucediendo, y por supuesto significa que hay potencialmente menos copias en cada paso.

Por otro lado, cuando hace desea mantener el resto del contexto, let tiene más sentido.

+9

¿El uso de uno u otro afecta el SQL generado? –

43

La principal diferencia es let que inyecta la variable en el contexto/ámbito, donde into crea un nuevo contexto/alcance.

0

Queriendo saber la diferencia en el lado de la base de datos, escribió 2 consultas de Entity Framework.

  • Vamos

    from u in Users 
    let noVowel = u.FirstName.Replace("a","").Replace("e","").Replace("i","") 
    where noVowel.Length >5 
    select new {u.FirstName, noVowel} 
    
  • En

    from u in Users 
    select u.FirstName.Replace("a","").Replace("e","").Replace("i","") 
    into noVowel 
    where noVowel.Length >5 
    select noVowel 
    

Los LSQ generados son casi idénticos . El SQL no es perfecto, el mismo código de proceso de cadena se repite en 2 lugares (donde y seleccione).

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 

Aquí es el SQL generado por LINQ a 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 LINQ to SQL es más inteligente de Entity Framework, proceso realizado cadena de una sola vez.

Cuestiones relacionadas