87 votes

Le mot-clé let de linq est-il meilleur que son mot-clé into ?

Je suis actuellement en train de réviser mes connaissances sur LINQ et j'essaie de comprendre la différence entre la fonction let et en utilisant le into mot-clé. Jusqu'à présent, le let semble meilleur que le mot-clé into mot-clé, d'après ce que j'ai compris.

Le site into permet essentiellement de poursuivre une requête après une projection. (Je veux juste préciser explicitement que je ne fais pas référence à celui pour la jointure de groupes).

Étant donné un tableau de noms, il 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 le place dans le dossier de l'utilisateur. noVowel qui permet ensuite d'introduire des where , orderby et select clauses. Une fois que le noVowel est créée, la variable n variable n'est plus disponible.

Le site let d'autre part, utilise des types anonymes temporaires pour vous permettre de réutiliser plus d'une variable à la fois.

Vous pouvez procéder comme suit :

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

Les deux noVowel et n sont disponibles pour être utilisées (même si je ne l'ai pas utilisé dans ce cas).

Bien que je puisse voir la différence, je n'arrive pas à comprendre pourquoi on voudrait utiliser l'option into sur le mot-clé let à moins que l'on veuille explicitement s'assurer que les variables précédentes ne puissent pas être utilisées dans les dernières parties de la requête.

Alors, y a-t-il une bonne raison pour que les deux mots-clés existent ?

0 votes

Est-ce une faute de frappe dans let exemple - where noVowel Qu'est-ce que c'est ? noVowel dans ce cas ?

85voto

Jon Skeet Points 692016

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 généralement préfèrent 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 en notation par points sur deux lignes, mais passons...).

Souvent, vous n'avez pas veulent tout le bagage de la première partie de la requête - c'est-à-dire quand vous utilisez select ... into ou diviser la requête en deux comme dans l'exemple ci-dessus. Cela signifie non seulement que les premières parties de la requête ne peuvent pas être utilisées quand elles ne devraient pas l'être, mais aussi que cela simplifie ce qui se passe et, bien sûr, qu'il y a potentiellement moins de copie à chaque étape.

D'autre part, lorsque vous faire veulent garder le reste du contexte, let est plus logique.

9 votes

L'utilisation de l'un ou l'autre affecte-t-elle le SQL généré ?

44voto

leppie Points 67289

La principale différence est le let injecte la variable dans le contexte/la portée, où into crée un nouveau contexte/scope.

1voto

Rm558 Points 1286

Voulant connaître la différence du côté de la base de données, j'ai écrit 2 requêtes Entity Framework.

  • Soit

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

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

Les SQLs générés sont presque identique . Le SQL n'est pas parfait, le même code de processus de chaîne est répété à 2 endroits (where et select).

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

Il semble que Linq-to-SQL soit plus intelligente que Entity Framework, le processus de chaîne n'est effectué qu'une seule fois.

0voto

snr Points 4881

Version visualisée de La réponse de leppie . Comme on peut le voir, le compilateur produit une erreur dans la requête avec into contrairement à cette dernière qui accède à la première variable.

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X