代码之家  ›  专栏  ›  技术社区  ›  mezoid

linq的let关键字是否比into关键字更好?

  •  84
  • mezoid  · 技术社区  · 16 年前

    我现在正在学习LINQ,并试图理解 let 并使用 into 关键字。到目前为止 关键字似乎比 进入之内 据我所知,关键词。

    这个 进入之内 关键字基本上允许在投影之后继续查询。(只想明确地声明,我不是指用于组联接的组。)

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

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

    它获取select的结果并将其放入 noVowel 变量,然后允许引入附加的 where , orderby select 条款。一旦 诺维欧 变量被创建, n 变量不再可用。

    这个 另一方面,关键字使用临时匿名类型,一次可以重用多个变量。

    您可以执行以下操作:

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

    两个 诺维欧 n 变量可以使用(即使我在本例中没有使用过)。

    虽然我能看出区别,但我不太明白为什么要使用 进入之内 关键字覆盖 关键字,除非有人明确希望确保前面的变量不能用于查询的后面部分。

    那么,这两个关键词的存在有充分的理由吗?

    3 回复  |  直到 16 年前
        1
  •  83
  •   Jon Skeet    16 年前

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

    select ... into 有效地隔离整个查询,并允许您将其用作新查询的输入。就我个人而言 通常 最好通过两个变量来实现这一点:

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

    (不可否认,在这种情况下,我会在两行中使用点符号,但忽略了这一点…)

    通常你不会 希望 查询的早期部分的全部行李-即当您使用 选择…进入之内 或者根据上面的示例将查询拆分为两个。这不仅意味着不应该使用查询的早期部分,而且还简化了正在进行的工作——当然,这意味着在每个步骤中进行的复制可能更少。

    另一方面,当你 想要保留其余的内容, let 更有意义。

        2
  •  43
  •   leppie    16 年前

    主要区别在于 let 将变量注入上下文/范围,其中 into 创建新的上下文/作用域。

        3
  •  1
  •   Rm558    8 年前

    为了了解数据库端的区别,编写了两个实体框架查询。

    • 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并不完美,相同的字符串过程代码在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 to 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是 更聪明的 而不是实体框架,字符串进程只执行一次。