linq的let关键字比关键字更好吗?

我正在刷新LINQ,并试图理解let和使用into关键字之间的区别。 就我的理解而言,到目前为止, let关键字似乎比into关键字更好。

into关键字本质上允许在投影之后继续查询。 (只是想明确指出,我不是指组join。)

给定一个名称的数组,它允许执行以下操作:

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

它将select的结果放到noVowelvariables中,然后允许引入附加的whereorderbyselect子句。 一旦noVowelvariables被创build, nvariables不再可用。

另一方面, let关键字使用临时匿名types来允许您一次重用多个variables。

您可以执行以下操作:

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

noVowelnvariables都可以使用(尽pipe在这种情况下我没有使用它)。

虽然我可以看到不同之处,但我不明白为什么要使用关键字let关键字,除非明确地要确保以前的variables不能在查询的后面部分中使用。

那么,为什么这两个关键词都存在是否有很好的理由?

是的,因为他们正在做不同的事情,正如你所说的。

select ... into有效隔离整个查询,并可以将其用作新查询的input。 我个人通常喜欢通过两个variables来做到这一点:

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

(无可否认,在这种情况下,我会用两行中的点符号来实现,但是忽略这一点…)

通常,你不需要查询的早期部分的整个行李 – 这就是当你使用select ... into或者按照上面的例子将查询分成两部分的时候。 这不仅意味着查询的早期部分不应该被使用,而且简化了正在发生的事情 – 当然这意味着在每一步都有可能减less复制的次数。

另一方面,当你想保留其他的语境时, let更有意义。

主要区别在于let将variables注入上下文/作用域,其中into创build新的上下文/作用域。

想知道DB侧的差异,写了2个entity framework查询。

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

生成的SQL几乎相同 。 SQL不完美,相同的string处理代码在2个地方(where和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 

这里是由LINQ到SQL生成的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比entity framework更聪明 ,string进程只执行一次。