คำหลัก let ของ linq ดีกว่าคำหลักหรือไม่?


86

ตอนนี้ฉันกำลังใช้ LINQ และกำลังพยายามทำความเข้าใจความแตกต่างระหว่างคำหลักletและการใช้intoคำหลัก จนถึงตอนนี้letคีย์เวิร์ดดูเหมือนดีกว่าintoคีย์เวิร์ดเท่าที่ฉันเข้าใจ

โดยintoหลักแล้วคำหลักช่วยให้สามารถดำเนินการสืบค้นต่อไปได้หลังจากการฉายภาพ (เพียงต้องการระบุอย่างชัดเจนว่าฉันไม่ได้หมายถึงหนึ่งในการเข้าร่วมกลุ่ม)

ด้วยอาร์เรย์ของชื่อที่อนุญาตให้ทำสิ่งต่อไปนี้:

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

มันต้องใช้ผลมาจากการเลือกและวางมันลงไปในnoVowelตัวแปรแล้วซึ่งช่วยให้หนึ่งที่จะแนะนำเพิ่มเติมwhere, orderbyและselectข้อ เมื่อnoVowelสร้างnตัวแปรแล้วตัวแปรจะไม่สามารถใช้ได้อีกต่อไป

ในทางกลับกันletคำหลักจะใช้ประเภทที่ไม่ระบุตัวตนชั่วคราวเพื่อให้คุณสามารถใช้ตัวแปรได้มากกว่าหนึ่งตัวแปรในแต่ละครั้ง

คุณสามารถทำสิ่งต่อไปนี้:

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

มีทั้งตัวแปรnoVowelและnตัวแปร (แม้ว่าฉันจะไม่ได้ใช้ในกรณีนี้)

แม้ว่าฉันจะเห็นความแตกต่าง แต่ฉันก็ไม่เข้าใจว่าทำไมใคร ๆ จึงต้องการใช้intoคีย์เวิร์ดกับletคีย์เวิร์ดเว้นแต่ว่าจะมีใครต้องการอย่างชัดเจนเพื่อให้แน่ใจว่าตัวแปรก่อนหน้านี้ไม่สามารถใช้ในส่วนหลังของคิวรีได้

มีเหตุผลที่ดีหรือไม่ที่ทำให้คำหลักทั้งสองมีอยู่


มันเป็นคำสะกดผิดในletเช่น - where noVowelสิ่งที่เป็นnoVowelในกรณีที่?
sll

คำตอบ:


85

ใช่เพราะพวกเขากำลังทำสิ่งที่แตกต่างอย่างที่คุณเคยพูดไว้

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;

(เป็นที่ยอมรับในกรณีนี้ฉันจะใช้สัญกรณ์จุดเป็นสองบรรทัด แต่ไม่สนใจว่า ... )

บ่อยครั้งที่คุณไม่ต้องการสัมภาระทั้งหมดของส่วนก่อนหน้าของข้อความค้นหาซึ่งเป็นเวลาที่คุณใช้select ... intoหรือแยกการสืบค้นเป็นสองส่วนตามตัวอย่างข้างต้น ไม่เพียง แต่หมายความว่าไม่สามารถใช้ส่วนก่อนหน้าของแบบสอบถามได้เมื่อไม่ควร แต่ยังช่วยลดความซับซ้อนของสิ่งที่เกิดขึ้นและแน่นอนว่าอาจมีการคัดลอกน้อยลงในแต่ละขั้นตอน

ในทางกลับกันเมื่อคุณไม่ต้องการรักษาบริบทที่เหลือไว้ให้letเหมาะสมยิ่งขึ้น


9
การใช้งานอย่างใดอย่างหนึ่งมีผลต่อ SQL ที่สร้างขึ้นหรือไม่
Pat Niemeyer

44

ความแตกต่างหลักคือการletแทรกตัวแปรลงในบริบท / ขอบเขตโดยที่intoสร้างบริบท / ขอบเขตใหม่


1

ต้องการทราบความแตกต่างในฝั่ง DB จึงเขียนแบบสอบถาม Entity Framework 2 รายการ

  • ปล่อย

    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
    

SQLs สร้างเกือบจะเหมือนกัน SQL ไม่สมบูรณ์โค้ดกระบวนการสตริงเดียวกันซ้ำ 2 ตำแหน่ง (โดยที่และเลือก)

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

นี่คือ SQL ที่สร้างโดย 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 จะฉลาดกว่า Entity Framework กระบวนการสตริงดำเนินการเพียงครั้งเดียว


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.