c# - tutorial - ¿La palabra clave let de linq es mejor que su palabra clave?
sintaxis linq c# (3)
La principal diferencia es que let
inyecta la variable en el contexto / scope, donde into
crea un nuevo contexto / scope.
Actualmente estoy revisando LINQ y estoy tratando de comprender la diferencia entre let
y usar la palabra clave into
. Hasta ahora, la palabra clave let
parece mejor que la palabra clave into
en lo que a mí respecta.
La palabra clave into
esencia le permite a uno continuar una consulta después de una proyección. (Solo quiero indicar explícitamente que no me estoy refiriendo a la unión grupal).
Dada una variedad de nombres, permite hacer lo siguiente:
var intoQuery =
from n in names
select Regex.Replace(n, "[aeiou]", "")
into noVowel
where noVowel.Length > 2
select noVowel;
Toma el resultado de la selección y lo coloca en la variable noVowel
que luego permite introducir cláusulas where
, orderby
y select
adicionales. Una vez que se noVowel
variable noVowel
, la variable n
ya no está disponible.
La palabra clave let
, por otro lado, usa tipos temporales anónimos para permitirle reutilizar más de una variable a la vez.
Puedes hacer lo siguiente:
var letQuery =
from n in names
let noVowel = Regex.Replace(n, "[aeiou]", "")
where noVowel.Length > 2
select noVowel;
Las variables noVowel
n
están disponibles para su uso (aunque no lo he usado en este caso).
Si bien puedo ver la diferencia, no puedo entender por qué uno querría usar la palabra clave into
en lugar de la palabra clave let
menos que uno explícitamente quisiera asegurarse de que las variables anteriores no puedan ser utilizadas en las últimas partes de la consulta.
Entonces, ¿hay una buena razón por la cual ambas palabras clave existen?
Queriendo saber la diferencia en el lado de la base de datos, escribió 2 consultas de Entity Framework.
Dejar
from u in Users let noVowel = u.FirstName.Replace("a","").Replace("e","").Replace("i","") where noVowel.Length >5 select new {u.FirstName, noVowel}
Dentro
from u in Users select u.FirstName.Replace("a","").Replace("e","").Replace("i","") into noVowel where noVowel.Length >5 select noVowel
Los SQL 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í está el SQL generado por 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 Linq-to-SQL es más inteligente que Entity Framework, el proceso de cadena se realiza solo una vez.
Sí, porque están haciendo cosas diferentes, como dices.
select ... into
in aísla efectivamente la totalidad de una consulta y le permite usarla como entrada para una nueva consulta. Personalmente, generalmente prefiero hacer esto 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 notación de puntos en dos líneas, pero ignorando eso ...)
A menudo no quiere todo el equipaje de la parte anterior de la consulta, que es cuando usa select ... into
o dividir la consulta en dos como se muestra en 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 quieras mantener el resto del contexto, let
tenga más sentido.