Từ khóa let của linq có tốt hơn từ khóa into của nó không?


86

Tôi hiện đang tìm hiểu về LINQ và đang cố gắng hiểu sự khác biệt giữa letcách sử dụng và intotừ khóa. Cho đến nay lettừ khóa có vẻ tốt hơn intotừ khóa theo như sự hiểu biết của tôi.

Các intotừ khóa cơ bản cho phép một để tiếp tục truy vấn sau một chiếu. (Chỉ muốn nói rõ ràng rằng tôi không đề cập đến người tham gia nhóm.)

Với một mảng tên, nó cho phép người ta thực hiện những việc sau:

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

Phải mất kết quả của lựa chọn và đặt nó vào trong noVowelbiến mà sau đó cho phép một để giới thiệu thêm where, orderbyselectmệnh đề. Khi noVowelbiến được tạo, nbiến không còn khả dụng nữa.

Mặt khác let, từ khóa sử dụng các kiểu ẩn danh tạm thời để cho phép bạn sử dụng lại nhiều biến cùng một lúc.

Bạn có thể làm như sau:

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

Cả biến noVowelnđều có sẵn để sử dụng (mặc dù tôi chưa sử dụng nó trong trường hợp này).

Mặc dù tôi có thể thấy sự khác biệt, nhưng tôi không thể hiểu được lý do tại sao người ta muốn sử dụng intotừ khóa thay cho lettừ khóa trừ khi người ta muốn chắc chắn rằng các biến trước đó không thể được sử dụng trong phần sau của truy vấn.

Vì vậy, có lý do chính đáng tại sao cả hai từ khóa tồn tại?


Đó có phải là lỗi đánh máy trong letví dụ - where noVowel, noVoweltrong trường hợp đó là gì?
sll

Câu trả lời:


85

Có, bởi vì họ đang làm những điều khác nhau, như bạn đã nói.

select ... intocô lập hiệu quả toàn bộ một truy vấn và cho phép bạn sử dụng nó làm đầu vào cho một truy vấn mới. Cá nhân tôi thường thích làm điều này thông qua hai biến:

var tmp = from n in names
          select Regex.Replace(n, "[aeiou]", "");

var noVowels = from noVowel in tmp
               where noVowel.Length > 2
               select noVowel;

(Phải thừa nhận trong trường hợp này, tôi sẽ làm điều đó với ký hiệu dấu chấm trong hai dòng, nhưng bỏ qua điều đó ...)

Thường thì bạn không muốn toàn bộ phần trước của truy vấn - đó là khi bạn sử dụng select ... intohoặc chia truy vấn thành hai như theo ví dụ trên. Điều đó không chỉ có nghĩa là các phần trước đó của truy vấn không thể được sử dụng khi chúng không nên, nó còn đơn giản hóa những gì đang diễn ra - và tất nhiên điều đó có nghĩa là có khả năng ít sao chép hơn ở mỗi bước.

Mặt khác, khi bạn làm muốn giữ lại phần còn lại của bối cảnh, letý nghĩa hơn.


9
Việc sử dụng cái này hay cái khác có ảnh hưởng đến SQL được tạo không?
Pat Niemeyer

44

Sự khác biệt chính là việc letđưa biến vào ngữ cảnh / phạm vi, nơi intotạo bối cảnh / phạm vi mới.


1

Muốn biết sự khác biệt ở phía DB, đã viết 2 truy vấn Entity Framework.

  • Để cho

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

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

Các SQL được tạo gần như giống hệt nhau . SQL không hoàn hảo, mã quy trình chuỗi giống nhau được lặp lại ở 2 nơi (ở đâu và chọn).

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

Đây là SQL được tạo bởi 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

Có vẻ như Linq-to-SQL thông minh hơn Entity Framework, quá trình chuỗi chỉ được thực hiện một lần.


0

Phiên bản trực quan của câu trả lời của leppie . Như có thể thấy, trình biên dịch tạo ra lỗi trong truy vấn intokhông giống như truy vấn sau khi truy cập vào biến đầu tiên.

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.