Is linq let a better keyword than its keyword?

I am currently browsing LINQ and trying to understand the difference between let and using the into keyword. So far, the let keyword seems to be better than the into keyword, as I understand it.

The into keyword allows you to continue the query after projection. (I just want to explicitly indicate that I do not mean the link for group joining.)

Given an array of names, it allows you to do the following:

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

It takes the result of the selection and puts it in the noVowel variable, which then allows you to enter additional where , orderby and select orderby . After creating the noVowel variable, n no longer available.

The let keyword, on the other hand, uses temporary anonymous types, allowing you to reuse more than one variable at a time.

You can do the following:

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

Both variables noVowel and n are available for use (although I did not use it in this case).

As long as I see the difference, I cannot understand why I need to use the into keyword with the let keyword, unless I explicitly wanted the previous variables to not be used in the last parts of the query.

So, is there a good reason why both words exist?

+83
c # linq
Mar 13 '09 at 9:25
source share
3 answers

Yes, because they do different things, as you said.

select ... into effectively isolates the entire single query and allows you to use it as the input of a new query. Personally, I usually prefer to do this with two variables:

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

(Admittedly, in this case, I would do it with dot notation in two lines, but ignoring it ...)

Often you do not need all the baggage of the previous part of the request - this is when you use select ... into or split the request in two in accordance with the above example. This not only means that the previous parts of the request cannot be used when it should not be, it simplifies what happens - and, of course, this means that less copies occur at each step.

On the other hand, when you want to keep the rest of the context, let makes more sense.

+80
Mar 13 '09 at 9:30 a.m.
source share

The main difference is that let introduces the variable into the context / scope, where into creates a new context / scope.

+42
Mar 13 '09 at 9:37
source share

Wanting to know the difference on the database side, I wrote 2 Entity Framework queries.

  • Let be

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

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

The generated SQL is almost identical . SQL is not perfect, the same line sequence code is repeated in 2 places (where to choose).

 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 

Here is the SQL generated by 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 

Linq-to-SQL seems to be smarter than the Entity Framework, the string process runs only once.

0
May 05 '17 at 10:04 pm
source share



All Articles