การแสดงออกอย่างคล่องแคล่วและการสืบค้น - มีประโยชน์อย่างใดอย่างหนึ่งต่อกันหรือไม่?


255

LINQ เป็นหนึ่งในการปรับปรุงที่ยิ่งใหญ่ที่สุดสำหรับ. NET ตั้งแต่ generics และช่วยให้ฉันตันของเวลาและบรรทัดของรหัส อย่างไรก็ตามไวยากรณ์ที่คล่องแคล่วดูเหมือนจะเป็นธรรมชาติสำหรับฉันมากกว่าไวยากรณ์ของนิพจน์แบบสอบถาม

var title = entries.Where(e => e.Approved)
    .OrderBy(e => e.Rating).Select(e => e.Title)
    .FirstOrDefault();

var query = (from e in entries
             where e.Approved
             orderby e.Rating
             select e.Title).FirstOrDefault();

มีความแตกต่างระหว่างสองคนนี้หรือไม่และมีประโยชน์อย่างใดอย่างหนึ่งของอีกคนหนึ่ง?


1
สำหรับเคียวรีที่ซับซ้อนฉันพบแลมบ์ดาไวยากรณ์ที่เข้าใจได้ง่ายขึ้น / อ่านได้ แต่ไวยากรณ์เคียวรีเพียงแค่สวยกว่า
nawfal

คำตอบ:


255

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

  • เมื่อใช้คำหลัก let
  • เมื่อคุณมีเครื่องกำเนิดไฟฟ้าหลายเครื่อง ( จากคำสั่ง)
  • เมื่อเข้าร่วม

นี่คือตัวอย่าง (จากตัวอย่าง LINQPad):

string[] fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };

var query =
  from fullName in fullNames
  from name in fullName.Split()
  orderby fullName, name
  select name + " came from " + fullName;

เปรียบเทียบสิ่งนี้กับสิ่งเดียวกันในไวยากรณ์เมธอด:

var query = fullNames
  .SelectMany (fName => fName.Split().Select (name => new { name, fName } ))
  .OrderBy (x => x.fName)
  .ThenBy  (x => x.name)
  .Select  (x => x.name + " came from " + x.fName);

ในทางกลับกันเมธอดไวยากรณ์จะแสดงขอบเขตทั้งหมดของตัวดำเนินการคิวรีและทำให้รัดกุมมากขึ้นด้วยคิวรีแบบง่าย คุณสามารถใช้ประโยชน์จากทั้งสองโลกได้อย่างดีที่สุดโดยผสมการสืบค้นและไวยากรณ์ของวิธีการ สิ่งนี้มักจะทำในการสืบค้น LINQ ไปยัง SQL:

var query =
  from c in db.Customers
  let totalSpend = c.Purchases.Sum (p => p.Price)    // Method syntax here
  where totalSpend > 1000
  from p in c.Purchases
  select new { p.Description, totalSpend, c.Address.State };

2
คำตอบที่ดี คุณช่วยเล่าเพิ่มเติมเกี่ยวกับสิ่งที่ ".Select (name => new {name, fName})" ได้ไหม?
quillbreaker

12
มันเลือกคำแต่ละคำ (แอนน์วิลเลียมส์จอห์น ฯลฯ ) พร้อมกับชื่อเต็มในประเภทที่ไม่ระบุชื่อ วิธีนี้ช่วยให้คุณ "พกพา" ชื่อเต็มดั้งเดิมเพื่อให้คุณสามารถเข้าถึงได้ทั้งชื่อเต็มและแต่ละคำในส่วนที่เหลือของแบบสอบถาม
Joe Albahari

58

ฉันชอบที่จะใช้หลัง (บางครั้งเรียกว่า "ไวยากรณ์ความเข้าใจแบบสอบถาม") เมื่อฉันสามารถเขียนนิพจน์ทั้งหมดด้วยวิธีนั้น

var titlesQuery = from e in entries
                  where e.Approved
                  orderby e.Rating
                  select e.Titles;

var title = titlesQuery.FirstOrDefault();

ทันทีที่ฉันต้องเพิ่ม (วงเล็บ) และ.MethodCalls()ฉันจะเปลี่ยน

เมื่อฉันใช้อดีตฉันมักจะใส่หนึ่งประโยคต่อบรรทัดเช่นนี้

var title = entries
    .Where (e => e.Approved)
    .OrderBy (e => e.Rating)
    .Select (e => e.Title)
    .FirstOrDefault();

ฉันพบว่าอ่านง่ายขึ้นเล็กน้อย


29

แต่ละสไตล์มีข้อดีและข้อเสีย ไวยากรณ์ของแบบสอบถามเป็น nicer เมื่อมันมาถึงการรวมและมันมีประโยชน์ให้คำหลักที่ทำให้การสร้างตัวแปรชั่วคราวภายในแบบสอบถามได้ง่าย

ไวยากรณ์ได้อย่างคล่องแคล่วในทางตรงกันข้ามมีวิธีการมากขึ้นและการดำเนินงานที่ไม่ได้เปิดเผยผ่านไวยากรณ์แบบสอบถาม นอกจากนี้เนื่องจากเป็นเพียงวิธีการขยายคุณสามารถเขียนของคุณเอง

ฉันได้พบว่าทุกครั้งที่ฉันเริ่มเขียนคำสั่ง LINQ โดยใช้ไวยากรณ์คิวรีฉันท้ายต้องใส่ไว้ในวงเล็บและถอยกลับไปใช้วิธีการขยาย LINQ อย่างคล่องแคล่ว ไวยากรณ์การสืบค้นมีคุณสมบัติไม่เพียงพอที่จะใช้ด้วยตัวเอง


"เนื่องจากเป็นเพียงวิธีการขยายที่คุณสามารถเขียนได้เอง" - คุณจะพบปัญหานี้หรือไม่? stackoverflow.com/a/3850254/1175496
The Red Pea

20

ในVB.NETฉันชอบไวยากรณ์การสืบค้นเป็นอย่างมาก

ฉันเกลียดที่จะทำซ้ำFunctionคำหลักน่าเกลียด:

Dim fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };
Dim query =
     fullNames.SelectMany(Function(fName) fName.Split().
     Select(Function(Name) New With {Name, fName})).
     OrderBy(Function(x) x.fName).
     ThenBy(Function(x) x.Name).
     Select(Function(x) x.Name & " came from " & x.fName)

แบบสอบถามที่เป็นระเบียบนี้สามารถอ่านและบำรุงรักษาได้มากกว่าในความคิดของฉัน:

query = From fullName In fullNames
        From name In fullName.Split()
        Order By fullName, name
        Select name & " came from " & fullName

ไวยากรณ์คิวรีของ VB.NET นั้นมีประสิทธิภาพมากกว่าและ verbose น้อยกว่าใน C #: https://stackoverflow.com/a/6515130/284240

ตัวอย่างเช่นแบบสอบถาม LINQ นี้ไปยังชุดข้อมูล (วัตถุ)

VB.NET:

Dim first10Rows = From r In dataTable1 Take 10

ค#:

var first10Rows = (from r in dataTable1.AsEnumerable() 
                   select r)
                   .Take(10);

9
ความเห็นอกเห็นใจของฉันสำหรับนักพัฒนา VB เหล่านั้นที่ไม่สามารถใช้รูปแบบแบบสอบถาม
nawfal

1
ตัวอย่าง C # สุดท้ายของคุณนั้นง่ายเกินไปที่จะมีค่า: คุณเพียงแค่เขียน `dataTable1.AsEnumerable (). Take (10);
Emyr

@Emyr: ย่อหน้าสุดท้ายของฉันซึ่งเริ่มต้นด้วย "ไวยากรณ์คิวรีของ VB.NET นั้นมีประสิทธิภาพมากกว่าและ verbose น้อยกว่าใน C #" เป็นเพียงการเปรียบเทียบไวยากรณ์คิวรีของ VB.NET กับ C # คุณกำลังใช้ไวยากรณ์เมธอด
Tim Schmelter

15

ฉันไม่ได้รับไวยากรณ์เคียวรีเลย ในใจของฉันไม่มีเหตุผล ให้สามารถรับได้ด้วย. Select และประเภทที่ไม่ระบุชื่อ ฉันแค่คิดว่าสิ่งต่าง ๆ ดูเป็นระเบียบมากขึ้นด้วย "เครื่องหมายวรรคตอน" ในนั้น


9
การเข้าร่วมหลายครั้งอาจทำให้ลำบากมากขึ้นอย่างรวดเร็วด้วยไวยากรณ์ที่คล่องแคล่ว ฉันมักจะใช้ความคล่องแคล่วของตัวเองแม้ว่า - ยกเว้นว่ามีส่วนร่วม
Roman Starkov

1
@Instance Hunter: เหมือนกันที่นี่ ฉันใช้เวลาพอสมควรที่จะเริ่มเข้าใจแนวคิดของไวยากรณ์ที่คล่องแคล่ว เมื่อรวมเข้ากับฟังก์ชั่นการนับจำนวนที่ทรงพลังและแนวคิดของ "บริสุทธิ์" ตอนนี้ฉันสนุกกับมันจริงๆ สำหรับส่วนของสมองนั้นยังคงเป็นประโยชน์หากมีไวยากรณ์คิวรี
Xan-Kun Clark-Davis

13

อินเทอร์เฟซที่คล่องแคล่วถ้ามีที่ไหน ถ้าฉันต้องการตัวเลือกหรือคำสั่งโดยฉันมักจะใช้ไวยากรณ์แบบสอบถาม


8

ดูเหมือนว่าไวยากรณ์ที่คล่องแคล่วจะมีประสิทธิภาพมากขึ้นแน่นอนว่ามันควรจะทำงานได้ดีขึ้นสำหรับการจัดระเบียบโค้ดเป็นวิธีการที่นำกลับมาใช้ใหม่ได้


5

ฉันรู้ว่าคำถามนี้ถูกติดแท็กด้วย C # แต่ไวยากรณ์ Fluent นั้นสร้างด้วย VB.NET อย่างเจ็บปวด


4

ฉันชอบไวยากรณ์ Fluent จริง ๆ และฉันพยายามใช้ในที่ที่ทำได้ แต่ในบางกรณีเช่นที่ฉันใช้การรวมฉันมักชอบไวยากรณ์ Query ในกรณีเหล่านั้นฉันคิดว่าอ่านง่ายขึ้นและฉันคิดว่าบางคน คุ้นเคยกับไวยากรณ์ Query (คล้าย SQL) มากกว่า lambdas


4

ในขณะที่ฉันเข้าใจและชอบรูปแบบที่คล่องแคล่วฉันติดอยู่กับ Query ในขณะนั้นเนื่องจากเหตุผลในการอ่าน ผู้ที่เพิ่งได้รับการแนะนำให้รู้จักกับ LINQ จะรู้สึกสะดวกสบายในการอ่าน


4

ฉันชอบไวยากรณ์แบบสอบถามเนื่องจากมาจากการเขียนโปรแกรมเว็บแบบดั้งเดิมโดยใช้ SQL มันง่ายกว่าที่ฉันจะพันหัว อย่างไรก็ตามฉันคิดว่าฉันจะเริ่มใช้ประโยชน์จาก. Where (แลมบ์ดา) เพราะมันสั้นกว่ามาก


4

ฉันใช้ Linq มาประมาณ 6 เดือนแล้ว เมื่อฉันเริ่มใช้มันฉันชอบไวยากรณ์แบบสอบถามเพราะมันคล้ายกับ T-SQL มาก

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


3

ฉันเพิ่งตั้งค่ามาตรฐาน บริษัท ของเราและเราบังคับใช้วิธีการส่วนขยาย ฉันคิดว่ามันเป็นความคิดที่ดีที่จะเลือกสิ่งใดสิ่งหนึ่งและอย่าผสมเป็นรหัส วิธีการขยายอ่านเพิ่มเติมเช่นรหัสอื่น ๆ

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

แต่ส่วนใหญ่เป็นเพียงการตั้งค่าส่วนตัวที่มีข้อยกเว้นเล็กน้อย


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