LINQ - Language Integrated Query (tạm dịch là ngôn ngữ truy vấn tích hợp) - là cách thức truy vấn dữ liệu từ một tập hợp dữ liệu. Hôm nay, chúng ta sẽ cùng tìm hiểu về LINQ và cách thức hoạt động của LINQ nhé.
Bạn đang xem: Linq
Nói đến lập trình, chúng ta không thể không nhắc đến dữ liệu. Dữ liệu ở đây có thể được bắt nguồn từ bộ nhớ, XML, cơ sở dữ liệu (Mysql, Sql Server...)... hay bất cứ nơi lưu trữ nào khác. Bất cứ dữ liệu đó bắt nguồn từ đâu, chúng ta phải luôn luôn thực hiện việc truy vấn dữ liệu đến nó. Với mỗi nguồn dữ liệu khác nhau sẽ có những cách khác nhau để thực hiện truy vấn.Ví dụ:- Nếu chúng ta có một danh sách được lưu trong bộ nhớ, chúng ta có thể sử dụng for, foreach kết hợp với các biểu thức so sánh để truy vấn dữ liệu.- Nếu chúng ta có dữ liệu trong file XML, chúng ta phải truy vấn từng node để có thể đưa ra các bản ghi hợp lệ.- Nếu chúng ta có dữ liệu trong cơ sở dữ liệu, chúng ta phải thực hiện truy vấn trong bảng rồi trả về các bản ghi hợp lệ.- ...Có lẽ đây là lý do mà các kỹ sư Microsoft đã thực hiện hợp nhất cách truy vấn thành 1 để có thể dùng chung cho các nguồn dữ liệu khác nhau. LINQ ra đời và được thêm vào phiên bản .NET 3.5.
LINQ cung cấp cho chúng ta những providers khác nhau để có thể truy vấn đến những nguồn dữ liệu khác nhau. Dưới đây là bảng providers và giải thích:
Tên provider | Mô tả |
LINQ to Objects | Sử dụng LINQ đối với các đối tượng collection mà implement từ IEnumerable hoặcIEnumerable (dữ liệu được lưu trong bộ nhớ). Được sử dụng rộng rãi đặc biệt đối với những bài toán cần hiệu năng cao. |
LINQ to SQL | Thực hiện map các tables, views, store procedures thành các đối tượng. LINQ sẽ thực hiện truy vấn trên các đối tượng đó bằng cách chuyển đổi qua lại giữa đối tượng và câu lệnh sql.Ngoài truy vấn ta cũng có thể thực hiện thêm/sửa/xóa dữ liệu dựa trên các đối tượng trên.Hỗ trợ transaction.Ưu điểm: được sử dụng khá nhiều trong thực tế dưới cái tên Entity Framework hoặc Entity Framework Core.Nhược điểm: chỉ làm việc với cơ sở dữ liệu là SQL Server. |
LINQ to Entities |
Tương tự như LINQ to SQL nhưng hỗ trợ nhiều loại cơ sở dữ liệu.Nhược điểm: sử dụng phức tạp. Nhiều cơ sở dữ liệu không thích hợp sử dụng chung với .Net.
Xem thêm: Thi 2016: Điều Chỉnh Quy Trình Xét Tuyển Đại Học 2016 Và Xét Tuyển Đh |
LINQ to DataSets | Sự kết hợp giữa LINQ và ADO.NET. |
LINQ toXML | Truy vấn thông tin trong file XML. |
Có 2 cách để tạo ra câu truy vấn: cú pháp truy vấn (query syntax) và cú pháp phương thức (method syntax). Và để viết được câu truy vấn bạn cần using thư viện System.Linq.Mình có đưa tạo ra class Car và danh sách các Car để làm ví dụ cho bài viết như sau:
public class Car { public int Id { get; set; } public string Name { get; set; } public int YearOfManufacture { get; set; } public override string ToString() { return string.Format("{0} - {1} - {2}", Id, Name, YearOfManufacture); } public static IList Cars { get { return new List { new Car { Id = 1, Name = "Honda", YearOfManufacture = 1990 }, new Car { Id = 2, Name = "Toyota", YearOfManufacture = 1880 }, new Car { Id = 3, Name = "Mazda", YearOfManufacture = 1925 }, new Car { Id = 4, Name = "VinFast", YearOfManufacture = 2017 }, new Car { Id = 5, Name = "KIA", YearOfManufacture = 1855 }, new Car { Id = 6, Name = "BMW", YearOfManufacture = 1946 }, new Car { Id = 7, Name = "Merc", YearOfManufacture = 1981 }, new Car { Id = 8, Name = "Abc", YearOfManufacture = 1920 }, new Car { Id = 9, Name = "Def", YearOfManufacture = 1940 }, new Car { Id = 10, Name = "Gij", YearOfManufacture = 1944 } }; } } }
var lists = from in select Ví dụ sau sẽ hiển thị danh sách các xe có năm sản xuất >= 1990.
class Program { static void Main(string args) { var cars = Car.Cars; var list = from item in cars where item.YearOfManufacture >= 1990 select item; foreach (var item in list) { Console.WriteLine(item); } /* * Output: * * 1 - Honda - 1990 * 4 - VinFast - 2017 */ Console.ReadKey(); } }Các bạn có thể tham khảo các phép toán truy vấn tại đây.Với cách viết như này, chúng ta sẽ rất dễ tiếp cận vì nó gần giống với truy vấn cơ sở dữ liệu nhưng chúng ta sẽ không hiểu được bản chất của LINQ là gì nên tôi sẽ không đi quá chi tiết. Vì khi biên dịch, cú pháp truy vấn cũng đưa về cú pháp phương thức.
Là những phương thức mở rộng của IEnumerable hoặc IEnumerable.Với ví dụ trên chúng ta thay đổi code như sau:
class Program { static void Main(string args) { var cars = Car.Cars; var list = cars.Where(f => f.YearOfManufacture >= 1990); foreach (var item in list) { Console.WriteLine(item); } /* * Output: * * 1 - Honda - 1990 * 4 - VinFast - 2017 */ Console.ReadKey(); } }Chúng ta để ý thấy rằng trong hàm Where xuất hiện tham số rất loằng ngoằng (f => f.YearOfManufacture >= 1990). Vậy tham số đó là gì vậy?Giờ chúng ta hãy xem signature của hàm Where:
public static IEnumerable Where(this IEnumerable source, Func predicate);Ohh, hóa ra nó là một biểu thức lambda mà mình đã đề cập chi tiết tại đây.Giờ chúng ta hãy thử viết một hàm LINQ mới như sau:
public static class CarExtenstion { public static IEnumerable MyQuery(this IEnumerable list, Func myCondition) { foreach (var item in list) { if (myCondition(item)) yield return item; } } }Chúng ta sử dụng hàm đó như sau:
class Program { static void Main(string args) { var cars = Car.Cars; var list = cars.MyQuery(f => f.YearOfManufacture >= 1990); foreach (var item in list) { Console.WriteLine(item); } /* * Output: * * 1 - Honda - 1990 * 4 - VinFast - 2017 */ Console.ReadKey(); } }Đến đây thì chúng ta đã hiểu LINQ sử dụng trong C# như thế nào và cách viết các hàm LINQ. Cuối cùng cũng là sự kết hợp giữa phương thức mở rộng, lambda expression và yield return.
Có 2 kịch bản để thực thi truy vấn:- Trì hoãn thực thi (Deferred Execution): việc thực thi truy vấn chỉ khi thực hiện foreach như hình dưới đây
class Program { static void Main(string args) { var cars = Car.Cars; var list = cars.Where(f => f.YearOfManufacture >= 1990).ToList(); foreach (var item in list) { Console.WriteLine(item); } /* * Output: * * 1 - Honda - 1990 * 4 - VinFast - 2017 */ Console.ReadKey(); } }
class Program { static void Main(string args) { var text = "531d"; var listGuid = RandomList(); var stopWatch = new Stopwatch(); stopWatch.Start(); var count = FindByFor(text, listGuid); stopWatch.Stop(); var ms = stopWatch.Elapsed.TotalMilliseconds; Console.WriteLine("For Execution Time: " + ms + " (ms). Count: " + count + " (items)"); stopWatch.Restart(); count = FindByForeach(text, listGuid); stopWatch.Stop(); ms = stopWatch.Elapsed.TotalMilliseconds; Console.WriteLine("Foreach Execution Time: " + ms + " (ms). Count: " + count + " (items)"); stopWatch.Restart(); count = FindByLinq(text, listGuid); stopWatch.Stop(); ms = stopWatch.Elapsed.TotalMilliseconds; Console.WriteLine("Linq Execution Time: " + ms + " (ms). Count: " + count + " (items)"); Console.ReadKey(); } private static int FindByFor(string text, IList listGuid) { var length = listGuid.Count; var count = 0; for (int i = 0; i listGuid) { var count = 0; foreach (var item in listGuid) { if (!item.Contains(text)) continue; count++; } return count; } private static int FindByLinq(string text, IList listGuid) { var list = listGuid.Where(f => f.Contains(text)); return list.Count(); } static IList RandomList() { var d = new List(); for (int i = 0; i Và kết quả của một số lần chạy thử như sau:Chỉ hơn kém nhau có 6 (ms).
Mình đã chia sẻ những hiểu biết của mình về LINQ, rất mong nó sẽ có ích cho các bạn. Nếu có thắc mắc gì, hãy để lại comment bên dưới nhé.