Saya sedang mempelajari kembali LINQ dan mencoba memahami perbedaan antara let
dan menggunakan into
kata kunci. Sejauh ini let
kata kunci tampaknya lebih baik daripada into
kata kunci sejauh pemahaman saya.
Kata into
kunci pada dasarnya memungkinkan seseorang untuk melanjutkan kueri setelah proyeksi. (Hanya ingin menyatakan secara eksplisit bahwa saya tidak merujuk ke grup untuk bergabung.)
Diberikan berbagai nama, memungkinkan seseorang untuk melakukan hal berikut:
var intoQuery =
from n in names
select Regex.Replace(n, "[aeiou]", "")
into noVowel
where noVowel.Length > 2
select noVowel;
Dibutuhkan hasil pilih dan tempat ke dalam noVowel
variabel yang kemudian memungkinkan seseorang untuk memperkenalkan tambahan where
, orderby
dan select
klausa. Setelah noVowel
variabel dibuat, n
variabel tersebut tidak lagi tersedia.
Sebaliknya let
, kata kunci menggunakan jenis anonim sementara untuk memungkinkan Anda menggunakan kembali lebih dari satu variabel dalam satu waktu.
Anda dapat melakukan hal berikut:
var letQuery =
from n in names
let noVowel = Regex.Replace(n, "[aeiou]", "")
where noVowel.Length > 2
select noVowel;
Baik variabel noVowel
dan n
tersedia untuk digunakan (meskipun saya belum menggunakannya dalam kasus ini).
Meskipun saya dapat melihat perbedaannya, saya tidak begitu mengerti mengapa seseorang ingin menggunakan into
kata kunci di atas let
kata kunci kecuali seseorang secara eksplisit ingin memastikan bahwa variabel sebelumnya tidak dapat digunakan di bagian akhir kueri.
Jadi, adakah alasan bagus mengapa kedua kata kunci tersebut ada?
let
contoh -where noVowel
, apanoVowel
dalam kasus itu?Jawaban:
Ya, karena mereka melakukan hal yang berbeda, seperti yang Anda katakan.
select ... into
secara efektif mengisolasi keseluruhan satu kueri dan memungkinkan Anda menggunakannya sebagai masukan untuk kueri baru. Secara pribadi saya biasanya lebih suka melakukan ini melalui dua variabel:var tmp = from n in names select Regex.Replace(n, "[aeiou]", ""); var noVowels = from noVowel in tmp where noVowel.Length > 2 select noVowel;
(Memang dalam hal ini saya akan melakukannya dengan notasi titik dalam dua baris, tetapi mengabaikannya ...)
Seringkali Anda tidak menginginkan seluruh bagasi dari bagian awal kueri - yaitu saat Anda menggunakan
select ... into
atau membagi kueri menjadi dua seperti contoh di atas. Tidak hanya itu berarti bagian awal dari kueri tidak dapat digunakan pada saat yang tidak semestinya, tetapi juga menyederhanakan apa yang terjadi - dan tentu saja itu berarti kemungkinan penyalinan berkurang di setiap langkah.Di sisi lain, jika Anda memang ingin mempertahankan konteks lainnya,
let
lebih masuk akal.sumber
Perbedaan utamanya adalah
let
memasukkan variabel ke dalam konteks / cakupan, di manainto
membuat konteks / cakupan baru.sumber
Ingin mengetahui perbedaan di sisi DB, tulis 2 kueri Entity Framework.
Membiarkan
from u in Users let noVowel = u.FirstName.Replace("a","").Replace("e","").Replace("i","") where noVowel.Length >5 select new {u.FirstName, noVowel}
Ke
from u in Users select u.FirstName.Replace("a","").Replace("e","").Replace("i","") into noVowel where noVowel.Length >5 select noVowel
SQL yang dihasilkan hampir identik . SQL tidak sempurna, kode proses string yang sama diulangi di 2 tempat (di mana dan pilih).
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
Berikut adalah SQL yang dihasilkan oleh 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
Sepertinya Linq-to-SQL lebih pintar dari Entity Framework, proses string hanya dilakukan sekali.
sumber
Versi visual dari jawaban leppie . Seperti yang bisa dilihat, kompilator menghasilkan kesalahan dalam kueri dengan
into
tidak seperti yang terakhir saat mengakses variabel pertama.sumber