CodeGym /Các khóa học /C# SELF /Cú pháp LINQ: Method Syntax vs Query Syntax

Cú pháp LINQ: Method Syntax vs Query Syntax

C# SELF
Mức độ , Bài học
Có sẵn

1. Giới thiệu

Trong thế giới LINQ có hai "trường phái" viết truy vấn, hai style mà nhìn qua tưởng khác hẳn nhau. Đó là Query Syntax (cú pháp truy vấn) và Method Syntax (cú pháp phương thức). Nếu bạn từng nghĩ lập trình chỉ là logic khô khan, thì hôm nay tụi mình sẽ thêm chút nghệ thuật vào, vì chọn cú pháp cũng giống như chọn cọ hay bút chì: cả hai đều vẽ được, nhưng một cái hợp để tô màu, cái kia hợp để vẽ nét.

Tại sao lại có hai cú pháp? Câu hỏi hay đấy! Hãy tưởng tượng bạn muốn gọi cà phê. Bạn có thể nói: "Cho mình một ly espresso với sữa và một muỗng đường nhé?". Hoặc bạn ghi ra giấy: "Espresso. Sữa. 1 đường". Cả hai đều rõ ràng, nhưng một cái nghe thân thiện, cái kia thì ngắn gọn.

LINQ cũng vậy. Một cú pháp được tạo ra để giống SQL nhất có thể, còn cái kia thì "rất C#" và linh hoạt. Cuối cùng, compiler C# sẽ chuyển cả hai về cùng một thứ: gọi method. Nên chọn cái nào chủ yếu là vấn đề đọc code và sở thích cá nhân thôi.

Cùng xem qua cả hai nhé.

2. Method Syntax

Đây là kiểu bạn gọi các extension method của LINQ nối nhau bằng dấu chấm. Cách này rất phổ biến với dân .NET vì dễ thêm thao tác mới, kết quả luôn là IEnumerable<T>, và viết ngay trong code rất tiện.

Ví dụ: Lọc và sắp xếp sản phẩm


var filteredProducts = products
    .Where(p => p.Price < 1000)          // Lọc theo giá
    .OrderBy(p => p.Name)                // Sắp xếp theo tên
    .ToList();                           // Chuyển thành List<Product>

Where, OrderBy, và ToList — đều là extension method của LINQ, mỗi cái trả về một tập dữ liệu mới để xử lý tiếp.

Sơ đồ


graph LR
A[products] --> B[Where]
B --> C[OrderBy]
C --> D[ToList]
Chuỗi gọi method trong Method Syntax

Điểm mạnh của Method Syntax

  • Rất linh hoạt: dễ xây chuỗi thao tác phức tạp.
  • Tất cả đều là method C#, IDE hỗ trợ autocomplete cực tốt.
  • Làm được gần như mọi thứ trong LINQ (thậm chí hơn).

Ví dụ nữa: lấy tên user trên 18 tuổi

Giả sử có class User:


public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Giờ lấy tên các user trưởng thành:


List<User> users = ... // khai báo đâu đó

var adultNames = users
    .Where(u => u.Age >= 18)
    .Select(u => u.Name)
    .ToList();

3. Query Syntax (cú pháp giống SQL)

Cú pháp này được tạo ra để dân C# cảm thấy quen thuộc nếu từng dùng SQL. Nó giống truy vấn database và bắt đầu bằng từ khóa from.

Ví dụ: cũng là lọc và sắp xếp


var filteredProducts = 
    from p in products
    where p.Price < 1000
    orderby p.Name
    select p;

Đọc như truy vấn kinh điển: "từ collection products lấy p, nơi p.Price < 1000, sắp xếp theo p.Name, chọn p".

Sơ đồ


flowchart TD
    A[products] -->|from p in products| B[where p.Price < 1000]
    B --> C[orderby p.Name]
    C --> D[select p]
Các bước truy vấn trong Query Syntax

Điểm mạnh của Query Syntax

  • Giống SQL, dễ hiểu cho ai từng làm database.
  • Dễ đọc hơn với truy vấn dài, nhiều điều kiện, group by, join (join).

Ví dụ nữa: lấy tên user trưởng thành


var adultNames = 
    from u in users
    where u.Age >= 18
    select u.Name;

Lưu ý: Ở đây sau select có thể chọn luôn trường cụ thể — ví dụ chỉ lấy tên.

4. So sánh: Method Syntax vs Query Syntax

Method Syntax Query Syntax
Cú pháp
users.Where(...).Select(...)
from u in users where ... select ...
Giống với Method chain bình thường SQL
Dùng ở đâu Luôn dùng được, mọi thao tác Không phải thao tác nào cũng có (ví dụ
Sum
,
Count
chỉ có ở Method Syntax)
Dễ đọc Ổn với chuỗi thao tác Dễ đọc hơn với group by, join
Kết quả trả về Thường là
IEnumerable<T>
Thường là
IEnumerable<T>
, nhưng đôi khi cần
.ToList()
để ra list

Fun fact ngoài đời thực

Hầu hết ví dụ trong docs chính thức của Microsoft về LINQ đều có cả hai style. Nhưng code thực tế thì Method Syntax ngày càng phổ biến — vì nó tiện khi dùng extension method (Where, Select, OrderBy v.v.).

Có nên trộn không? Chọn style nào?

Có thể mix cả hai style trong một project (thậm chí một truy vấn — nhưng nhìn hơi dị). Quan trọng là đừng biến code thành "salad". Thường thì chọn một style cho cả module hoặc project để dễ đọc.

Method Syntax cực hợp cho các thao tác tuần tự và dùng hết các LINQ method chỉ có ở dạng method (Sum, Count, Any và vài cái khác).

Query Syntax rất tiện cho bài toán join, group by hoặc điều kiện lồng nhiều tầng — lúc đó đọc dễ hơn hẳn.

5. Chuyển đổi giữa hai style: cùng một thứ, cách viết khác

LINQ trong C# sẽ biến mọi truy vấn kiểu SQL (Query Syntax) thành chuỗi gọi method (Method Syntax). Tức là bạn viết kiểu gì thì C# cũng dịch về extension method khi compile.

Ví dụ 1 — lọc:

Query Syntax:


var adults = from u in users
             where u.Age >= 18
             select u;

Method Syntax (tương đương):


var adults = users.Where(u => u.Age >= 18);

Ví dụ 2 — chọn trường (Select):

Query Syntax:


var names = from u in users
            select u.Name;

Method Syntax:


var names = users.Select(u => u.Name);

7. Group by và join (join, group by)

Tạo object mới

Giả sử app học tập của mình cần in ra danh sách user được group theo tuổi. Lúc này sự khác biệt cú pháp càng rõ.

Query Syntax (group by):


var usersByAge = 
    from u in users
    group u by u.Age into ageGroup
    select new { Age = ageGroup.Key, Users = ageGroup.ToList() };

Mình group user theo tuổi (group u by u.Age). Sau into sẽ có biến ageGroup — chính là group đó.

Method Syntax (tương đương):


var usersByAge = users
    .GroupBy(u => u.Age)
    .Select(ageGroup => new { Age = ageGroup.Key, Users = ageGroup.ToList() });

Khó hơn: join

Giả sử có danh sách đơn hàng (orders) và danh sách user (users). Mình muốn lấy tên user và tổng tiền đơn hàng của họ.

Query Syntax:


var userOrders =
    from user in users
    join order in orders on user.Id equals order.UserId
    select new { user.Name, order.Amount };

Method Syntax:


var userOrders = users.Join(
    orders,
    user => user.Id,
    order => order.UserId,
    (user, order) => new { user.Name, order.Amount }
);

8. Lỗi thường gặp, bẫy và mẹo nhỏ

Một trong những hiểu lầm phổ biến: nếu bạn không thêm .ToList(), kết quả không phải list mà là "truy vấn lười biếng" (lazy query), chỉ chạy khi duyệt lần đầu. Cái này tiện, nhưng có thể gây bất ngờ nếu collection gốc thay đổi sau khi viết truy vấn. Về "thực thi lười biếng" mình sẽ nói kỹ hơn (sau khi học các LINQ method).

Nhiều bạn mới hay nhầm là có thể dùng mọi LINQ method trong Query Syntax. Ví dụ, không thể viết select sum(u.Age), mà phải chuyển sang Method Syntax (users.Sum(u => u.Age)).

2
Nhiệm vụ
C# SELF, mức độ, bài học
Đã khóa
Áp dụng Query Syntax để lọc và sắp xếp
Áp dụng Query Syntax để lọc và sắp xếp
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION