Câu hỏi chúng tôi hay gặp nhất khi hướng dẫn dev mới: LINQ method syntax và query syntax, nên chọn loại nào? Bạn mở một dự án cũ của đồng nghiệp. Nửa file dùng dấu chấm nối chuỗi phương thức. Nửa file kia lại viết như câu lệnh SQL thu nhỏ. Cùng một ngôn ngữ, hai kiểu viết khác hẳn nhau. Không ai sai cả. Nhưng nếu không hiểu vì sao người ta chọn cách này thay vì cách kia, bạn dễ gặp rắc rối. Code viết ra lộn xộn, không nhất quán trong cùng một dự án.
LINQ Method Syntax Và Query Syntax: Hai Cách Viết Phổ Biến Trong .NET
LINQ là viết tắt của Language Integrated Query. Nói dễ hiểu, đây là cách C# cho bạn lọc, sắp xếp, nhóm dữ liệu ngay trong code. Bạn không cần tự viết vòng lặp thủ công nữa. .NET cho phép viết LINQ theo hai kiểu cú pháp khác nhau. Hiểu rõ khác biệt giúp bạn đọc code người khác nhanh hơn, và chọn đúng kiểu cho từng tình huống.
Method syntax là cách nối các phương thức mở rộng lại với nhau bằng dấu chấm. Ví dụ: danhSachSanPham.Where(p => p.Gia > 100000).OrderBy(p => p.Ten). Mỗi phương thức xử lý một bước: lọc, rồi sắp xếp. Đây là kiểu viết phổ biến nhất trong code .NET hiện đại. Lý do đơn giản: gõ nhanh, và IntelliSense trong Visual Studio gợi ý phương thức tiếp theo ngay khi bạn gõ dấu chấm.
Query syntax lại viết gần giống câu lệnh truy vấn cơ sở dữ liệu truyền thống. Cùng đoạn lọc và sắp xếp ở trên, đây là cách viết theo query syntax. From p in danhSachSanPham where p.Gia > 100000 orderby p.Ten select p. Cấu trúc bắt đầu bằng from, có where, có orderby, kết bằng select. Ai từng viết SQL sẽ thấy quen mắt ngay.
Về bản chất, cả hai đều được trình biên dịch C# dịch thành cùng một chuỗi lệnh gọi phương thức bên dưới. Query syntax chỉ là lớp vỏ dễ đọc, được compiler tự động chuyển thành method syntax lúc build. Vì vậy tốc độ chạy không chênh nhau. Chọn kiểu nào không ảnh hưởng hiệu năng ứng dụng.
| Tiêu chí | Method syntax | Query syntax |
|---|---|---|
| Cách viết | Nối chuỗi phương thức bằng dấu chấm, đọc từ trái qua phải theo từng bước xử lý | Giống câu lệnh truy vấn, bắt đầu bằng from và kết bằng select |
| Tốc độ gõ | Nhanh, nhờ IntelliSense gợi ý ngay sau dấu chấm | Chậm hơn một chút vì cú pháp dài |
| Hợp với | Thao tác đơn giản, ít điều kiện lọc | Truy vấn nhiều điều kiện, join nhiều nguồn dữ liệu, người quen SQL |
Lỗi hay gặp ở dev mới: cố nhồi mọi thao tác vào một kiểu duy nhất cho ra vẻ nhất quán. .NET lại cho phép trộn hai kiểu ngay trong cùng một biểu thức. Bạn có thể viết query syntax cho phần lọc phức tạp, rồi nối .ToList() hoặc .Count() theo method syntax ở cuối. Chúng tôi hay làm vậy khi query có join nhiều bảng nhưng vẫn cần đếm kết quả ngay sau đó.
Nhóm chúng tôi từng thống nhất một quy ước nội bộ về việc này. Dự án mới ưu tiên method syntax, chỉ chuyển sang query syntax khi truy vấn có từ hai điều kiện lọc trở lên. Quy ước này nằm trong tài liệu nguyên tắc chúng tôi áp dụng khi review code cho backend developer. Nhờ vậy cả nhóm đọc code của nhau nhanh hơn hẳn.
Khi Nào Nên Ưu Tiên Sử Dụng Method Syntax
Phần lớn thao tác hằng ngày, chúng tôi mặc định chọn method syntax. Nhanh gọn, ít phải nghĩ ngợi thêm.
Ưu tiên method syntax khi thao tác chỉ có một hoặc hai bước. Ví dụ: lọc một điều kiện, sắp xếp một cột, hoặc đếm số dòng thoả điều kiện. Lọc danh sách sản phẩm còn hàng chỉ cần: danhSach.Where(p => p.SoLuong > 0). Một dòng, đọc phát hiểu ngay.
Method syntax còn mạnh ở chỗ dễ nối thêm phương thức mở rộng khác. Những phương thức như .Count(), .Any(), .FirstOrDefault(), hay .Sum() cũng nối rất gọn. Nói dễ hiểu, đây là các hàm đếm, kiểm tra tồn tại, lấy phần tử đầu, hoặc tính tổng. Bạn gõ thêm dấu chấm là dùng ngay, không cần bọc lại cả câu query. Muốn dùng mấy hàm này từ query syntax vẫn phải chuyển qua method syntax ở cuối, nên viết thẳng method syntax từ đầu cho gọn.
Chúng tôi hay gặp tình huống này nhất ở trang lọc sản phẩm của các website bán hàng. Backend cần lọc nhanh theo giá, tồn kho, danh mục — chỉ bằng vài dòng LINQ. Nhưng lọc dữ liệu mượt chỉ là một phần của câu chuyện. Muốn trang bán hàng thật sự chuyển đổi tốt, phần thiết kế website bán hàng phía trước mới là yếu tố quyết định. Giao diện, luồng thanh toán, trải nghiệm trên di động mới là thứ giữ chân khách. Trang lọc sản phẩm mượt chỉ là điều kiện cần, chưa phải điều kiện đủ.
Mẹo Tránh Chuỗi Method Dài Dằng Dặc
Sai lầm dev mới hay mắc: nối quá nhiều .Where() liên tiếp cho từng điều kiện nhỏ lẻ. Chuỗi lệnh dài dằng dặc, khó đọc lại sau vài tháng. Vài mẹo chúng tôi áp dụng để tránh việc đó:
- Gộp các điều kiện liên quan vào một Where() duy nhất bằng toán tử && thay vì tách nhiều Where() rời rạc.
- Đặt tên biến trung gian rõ nghĩa cho từng bước xử lý dài, thay vì viết một chuỗi phương thức dài trên một dòng.
- Dùng var để khai báo biến, để trình biên dịch tự suy ra kiểu dữ liệu trả về, đỡ phải gõ kiểu generic dài dòng.
Ba mẹo này giúp code method syntax gọn mà vẫn dễ đọc lại, kể cả khi người đọc không phải là người viết ra nó.
Khi Nào Nên Ưu Tiên Sử Dụng Query Syntax
Có những đoạn code mà method syntax viết ra đọc rất mệt: quá nhiều dấu chấm, quá nhiều lambda lồng nhau. Đó là lúc query syntax phát huy tác dụng.
Khi Truy Vấn Có Join Hoặc Nhóm Dữ Liệu
Query syntax mạnh nhất khi truy vấn có join nhiều nguồn dữ liệu. Ví dụ nối danh sách đơn hàng với danh sách khách hàng, để lấy tên khách kèm tổng tiền đơn. Viết theo query syntax sẽ là: from o in danhSachDonHang join kh in danhSachKhachHang on o.KhachHangId equals kh.Id select new { kh.Ten, o.TongTien }. Viết bằng method syntax, đoạn này phải gọi .Join() với bốn tham số khó nhớ thứ tự. Query syntax giúp người đọc hình dung ngay bảng nào nối với bảng nào.
Một tình huống khác đáng dùng query syntax: gom nhóm đơn hàng theo tháng để tính doanh thu. Cú pháp group by trong query syntax đọc tự nhiên hơn hẳn so với .GroupBy() lồng nhiều lambda của method syntax. Chúng tôi từng sửa lại một đoạn báo cáo doanh thu viết toàn method syntax. Sau khi chuyển phần group by sang query syntax, đoạn code ngắn lại gần một phần ba. Đồng nghiệp review cũng đỡ mất thời gian hỏi lại logic.
Với những bạn xuất thân từ dân quản trị cơ sở dữ liệu, chuyển sang C# mà gặp query syntax sẽ thấy thân quen ngay. Cấu trúc from, where, orderby, select gần như bê nguyên cách tư duy khi viết truy vấn. Cách viết đó giống hệt trong các hệ quản trị cơ sở dữ liệu như SQL Server hay MySQL. Đây cũng là lý do nhiều team backend giữ thói quen này. Thành viên chuyển ngành từ DBA sang lập trình thường vẫn viết query syntax cho các đoạn lọc phức tạp.
Sai lầm chúng tôi từng thấy: có team ép toàn bộ dự án chỉ dùng query syntax cho nhất quán. Kể cả những đoạn lọc chỉ có một điều kiện cũng viết kiểu đó. Kết quả là code dài hơn cần thiết, mà không mang lại lợi ích đọc hiểu nào thêm. Query syntax chỉ thật sự đáng dùng khi truy vấn có từ hai điều kiện lọc, có join, hoặc có nhóm dữ liệu. Ngoài mấy trường hợp đó, quay lại method syntax vẫn nhanh và gọn hơn nhiều.
Chọn Cú Pháp Phù Hợp Với Thói Quen Và Dự Án Của Bạn
Nếu phải chọn một quy tắc duy nhất để nhớ, chúng tôi sẽ nói thế này. Nhìn vào số điều kiện lọc, trước khi đặt bút viết dòng LINQ đầu tiên. Một hoặc hai điều kiện đơn giản, cứ viết method syntax cho nhanh. Từ ba điều kiện trở lên, có join hoặc group by, chuyển sang query syntax để người đọc sau này đỡ vất vả. Quan trọng hơn cả việc syntax nào đúng syntax nào sai, là cả team thống nhất được lúc nào dùng cách nào. Tránh tình trạng mỗi người viết một kiểu trong cùng một file.
Ngoài LINQ, việc chọn giữa hai cách làm cùng một việc còn xuất hiện ở nhiều quyết định kỹ thuật khác trong nghề backend. Một ví dụ là bài so sánh giữa ASP.NET và PHP khi chọn ngôn ngữ cho dự án website mà chúng tôi từng viết. Càng làm lâu, bạn sẽ thấy phần lớn quyết định kỹ thuật không có đáp án tuyệt đối đúng. Chỉ có đáp án hợp với bối cảnh dự án đang làm, và hợp với chính thói quen đọc code của đội mình.

