Thông thạo và biểu hiện truy vấn - Có bất kỳ lợi ích nào của cái này hơn cái kia không?


255

LINQ là một trong những cải tiến lớn nhất đối với .NET kể từ generic và nó giúp tôi tiết kiệm hàng tấn thời gian và dòng mã. Tuy nhiên, cú pháp trôi chảy dường như trở nên tự nhiên hơn nhiều so với cú pháp biểu thức truy vấn.

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();

Có sự khác biệt nào giữa hai hoặc có bất kỳ lợi ích cụ thể nào so với nhau không?


1
Đối với các truy vấn phức tạp, tôi thấy cú pháp lambda dễ hiểu / dễ đọc hơn, nhưng cú pháp truy vấn chỉ đơn giản là đẹp hơn.
nawfal

Câu trả lời:


255

Không phải là tốt hơn: họ phục vụ các nhu cầu khác nhau. Cú pháp truy vấn xuất hiện khi bạn muốn tận dụng nhiều biến phạm vi . Điều này xảy ra trong ba tình huống:

  • Khi sử dụng từ khóa let
  • Khi bạn có nhiều máy phát điện ( từ mệnh đề)
  • Khi tham gia

Đây là một ví dụ (từ các mẫu 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;

Bây giờ so sánh điều này với điều tương tự trong cú pháp phương thức:

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);

Mặt khác, cú pháp phương thức hiển thị toàn bộ gam của toán tử truy vấn và ngắn gọn hơn với các truy vấn đơn giản. Bạn có thể tận dụng tốt nhất cả hai thế giới bằng cách trộn cú pháp truy vấn và phương thức. Điều này thường được thực hiện trong các truy vấn LINQ to 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
Câu trả lời tốt đẹp. Bạn có thể cho tôi biết thêm một chút về những gì ".Select (name => new {name, fName})" đang làm gì không?
quillbreaker

12
Nó chọn từ riêng lẻ (anne, williams, john, v.v.) cùng với tên đầy đủ trong một loại ẩn danh. Điều này cho phép bạn "mang" tên đầy đủ ban đầu để bạn có quyền truy cập vào cả tên đầy đủ và từ riêng lẻ trong phần còn lại của truy vấn.
Joe Albahari

58

Tôi thích sử dụng cái sau (đôi khi được gọi là "cú pháp hiểu truy vấn") khi tôi có thể viết toàn bộ biểu thức theo cách đó.

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

var title = titlesQuery.FirstOrDefault();

Ngay sau khi tôi phải thêm (dấu ngoặc đơn) và .MethodCalls(), tôi thay đổi.

Khi tôi sử dụng trước đây, tôi thường đặt một mệnh đề trên mỗi dòng, như thế này:

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

Tôi thấy rằng một chút dễ đọc hơn.


29

Mỗi phong cách có ưu và nhược điểm của họ. Cú pháp truy vấn đẹp hơn khi tham gia và nó có từ khóa let hữu ích giúp tạo các biến tạm thời bên trong một truy vấn dễ dàng.

Mặt khác, cú pháp trôi chảy có nhiều phương thức và thao tác hơn không được tiếp xúc thông qua cú pháp truy vấn. Ngoài ra vì chúng chỉ là phương pháp mở rộng, bạn có thể tự viết.

Tôi đã thấy rằng mỗi khi tôi bắt đầu viết một câu lệnh LINQ bằng cú pháp truy vấn, cuối cùng tôi phải đặt nó trong ngoặc đơn và quay lại sử dụng các phương thức mở rộng LINQ trôi chảy. Cú pháp truy vấn chỉ không có đủ tính năng để sử dụng.


"vì chúng chỉ là phương thức mở rộng mà bạn có thể tự viết." - bạn sẽ gặp vấn đề này? stackoverflow.com/a/3850254/1175496
Hạt đậu đỏ

20

Trong VB.NET tôi rất thích cú pháp truy vấn.

Tôi ghét lặp lại từ khóa xấu xí 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)

Theo tôi, truy vấn gọn gàng này dễ đọc và dễ bảo trì hơn nhiều:

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

Cú pháp truy vấn của VB.NET cũng mạnh hơn và ít dài dòng hơn trong C #: https://stackoverflow.com/a/6515130/284240

Ví dụ: truy vấn LINQ to Dataset (Đối tượng) này

VB.NET:

Dim first10Rows = From r In dataTable1 Take 10

C #:

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

9
Tôi đồng cảm với những nhà phát triển VB không thể sử dụng kiểu truy vấn.
nawfal

1
Ví dụ C # cuối cùng của bạn quá đơn giản để có giá trị: bạn chỉ cần viết `dataTable1.AsEnumerable (). Take (10);
Emyr

@Emyr: đoạn cuối cùng của tôi bắt đầu bằng "Cú pháp truy vấn của VB.NET cũng mạnh hơn và ít dài dòng hơn trong C #" chỉ là so sánh cú pháp truy vấn của VB.NET với C #, bạn đang sử dụng cú pháp phương thức.
Tim Schmelter

15

Tôi không nhận được cú pháp truy vấn nào cả. Không có lý do cho nó trong tâm trí của tôi. hãy để có thể đạt được với các loại .Select và nặc danh. Tôi chỉ nghĩ mọi thứ có vẻ ngăn nắp hơn với "dấu câu" trong đó.


9
Nhiều phép nối có thể khá tốn công khá nhanh với cú pháp trôi chảy. Tôi thường sử dụng thành thạo bản thân mình - trừ khi tham gia.
Roman Starkov

1
@Instance Hunter: Tương tự ở đây. Tôi mất khá nhiều thời gian để bắt đầu nắm bắt ý tưởng về cú pháp trôi chảy. Kết hợp với vô số mạnh mẽ và ý tưởng về các hàm "thuần túy", giờ đây tôi thực sự thích nó và các tình huống khó khăn trước đây không có biểu diễn mã đẹp. Đối với phần ye-ole-SQL của bộ não, vẫn có một cú pháp truy vấn.
Xan-Kun Clark-Davis

13

Giao diện trôi chảy nếu chỉ có một nơi. Nếu tôi cần chọn hoặc đặt hàng, tôi thường sử dụng cú pháp Truy vấn.


8

Cú pháp trôi chảy có vẻ thực sự mạnh mẽ hơn, nó cũng sẽ hoạt động tốt hơn để tổ chức mã thành các phương thức tái sử dụng nhỏ.


5

Tôi biết câu hỏi này được gắn thẻ C #, nhưng cú pháp Fluent rất dài dòng với VB.NET.


4

Tôi thực sự thích cú pháp Fluent và tôi cố gắng sử dụng nó ở nơi tôi có thể, nhưng trong một số trường hợp nhất định, ví dụ như khi tôi sử dụng phép nối, tôi thường thích cú pháp Truy vấn, trong những trường hợp đó tôi thấy dễ đọc hơn và tôi nghĩ một số người quen thuộc với cú pháp Truy vấn (giống như SQL), hơn lambdas.


4

Mặc dù tôi hiểu và thích định dạng trôi chảy, tôi vẫn bị truy vấn vì lý do dễ đọc. Những người vừa được giới thiệu về LINQ sẽ thấy Truy vấn thoải mái hơn nhiều để đọc.


4

Tôi thích cú pháp truy vấn vì tôi đến từ lập trình web truyền thống sử dụng SQL. Nó dễ dàng hơn nhiều để tôi quấn đầu xung quanh. Tuy nhiên, nó nghĩ rằng tôi sẽ bắt đầu sử dụng .Where (lambda) vì nó chắc chắn ngắn hơn nhiều.


4

Tôi đã sử dụng Linq khoảng 6 tháng nay. Khi tôi lần đầu tiên bắt đầu sử dụng, tôi thích cú pháp truy vấn vì nó rất giống với T-SQL.

Tuy nhiên, bây giờ tôi đang dần trở lại trước đây, vì thật dễ dàng để viết các đoạn mã có thể tái sử dụng làm phương thức mở rộng và chỉ cần xâu chuỗi chúng lại với nhau. Mặc dù tôi thấy việc đặt mỗi mệnh đề trên dòng riêng của nó sẽ giúp ích rất nhiều cho khả năng đọc.


3

Tôi vừa thiết lập các tiêu chuẩn của công ty chúng tôi và chúng tôi thi hành việc sử dụng các phương pháp Mở rộng. Tôi nghĩ rằng đó là một ý tưởng tốt để chọn cái khác và không trộn chúng vào mã. Các phương thức mở rộng đọc giống như các mã khác.

Cú pháp hiểu không có tất cả các toán tử và sử dụng dấu ngoặc đơn xung quanh truy vấn và thêm các phương thức mở rộng sau khi tất cả chỉ xin tôi sử dụng các phương thức mở rộng từ đầu.

Nhưng đối với hầu hết các phần, đó chỉ là sở thích cá nhân với một vài ngoại lệ.


3
Tôi sẽ không thực thi sở thích cá nhân .. Nhưng đó là tôi.
Memet Olsen
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.