Je suis actuellement en train de réviser LINQ et j'essaie de comprendre la différence entre le let
et l'utilisation du into
mot - clé. Jusqu'à présent, le let
mot - clé semble meilleur que le into
mot - clé dans la mesure où je comprends.
Le into
mot-clé permet essentiellement de poursuivre une requête après une projection. (Je veux juste indiquer explicitement que je ne fais pas référence à celui de la jointure de groupe.)
Étant donné un tableau de noms, cela permet de faire ce qui suit:
var intoQuery =
from n in names
select Regex.Replace(n, "[aeiou]", "")
into noVowel
where noVowel.Length > 2
select noVowel;
Il prend le résultat de la sélection et la place dans la noVowel
variable qui permet alors d'introduire d' autres where
, orderby
et les select
clauses. Une fois la noVowel
variable créée, la n
variable n'est plus disponible.
Le let
mot-clé, quant à lui, utilise des types anonymes temporaires pour vous permettre de réutiliser plusieurs variables à la fois.
Vous pouvez faire ce qui suit:
var letQuery =
from n in names
let noVowel = Regex.Replace(n, "[aeiou]", "")
where noVowel.Length > 2
select noVowel;
Les variables noVowel
et n
sont disponibles pour utilisation (même si je ne les ai pas utilisées dans ce cas).
Bien que je puisse voir la différence, je ne peux pas vraiment comprendre pourquoi on voudrait utiliser le into
mot - clé sur le let
mot - clé à moins que l'on ne veuille explicitement s'assurer que les variables précédentes ne pouvaient pas être utilisées dans les dernières parties de la requête.
Alors, y a-t-il une bonne raison pour laquelle les deux mots-clés existent?
let
exemple -where noVowel
, qu'est-ce que c'estnoVowel
dans ce cas?Réponses:
Oui, parce qu'ils font des choses différentes, comme vous l'avez dit.
select ... into
isole efficacement l'ensemble d'une requête et vous permet de l'utiliser comme entrée d'une nouvelle requête. Personnellement, je préfère généralement le faire via deux variables:var tmp = from n in names select Regex.Replace(n, "[aeiou]", ""); var noVowels = from noVowel in tmp where noVowel.Length > 2 select noVowel;
(Certes, dans ce cas, je le ferais avec une notation par points sur deux lignes, mais en ignorant cela ...)
Souvent, vous ne voulez pas tout le bagage de la partie précédente de la requête - c'est-à-dire lorsque vous utilisez
select ... into
ou divisez la requête en deux comme dans l'exemple ci-dessus. Non seulement cela signifie que les parties antérieures de la requête ne peuvent pas être utilisées alors qu'elles ne devraient pas l'être, mais cela simplifie ce qui se passe - et bien sûr, cela signifie qu'il y a potentiellement moins de copies à chaque étape.D'autre part, lorsque vous ne voulez garder le reste du contexte,
let
est plus logique.la source
La principale différence est l'
let
injection de la variable dans le contexte / la portée, oùinto
crée un nouveau contexte / portée.la source
Voulant connaître la différence côté DB, a écrit 2 requêtes Entity Framework.
Laisser
from u in Users let noVowel = u.FirstName.Replace("a","").Replace("e","").Replace("i","") where noVowel.Length >5 select new {u.FirstName, noVowel}
Dans
from u in Users select u.FirstName.Replace("a","").Replace("e","").Replace("i","") into noVowel where noVowel.Length >5 select noVowel
Les SQL générés sont presque identiques . Le SQL n'est pas parfait, le même code de processus de chaîne est répété à 2 endroits (où et sélectionnez).
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
Voici le SQL généré par 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
Semble Linq-to-SQL est plus intelligent que Entity Framework, le processus de chaîne effectué une seule fois.
la source
Version visualisée de la réponse de Leppie . Comme on peut le voir, le compilateur génère une erreur dans la requête avec,
into
contrairement à la dernière, l'accès à la première variable.la source