LINQ- Ngôn Ngữ Truy Vấn Tích Hợp Không Thể Không Biết

LINQ- Ngôn Ngữ Truy Vấn Tích Hợp Không Thể Không Biết

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é.

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.

Quý khách đang xem: LINQ- Ngôn Ngữ Truy Vấn Tích Hợp Không Thể Không Biết

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 hòa 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.

thành phần cấu thành linq

  • nguồn dữ liệu.
  • tạo câu lệnh truy vấn.
  • thực thi truy vấn để lấy kết quả.

1. nguồn dữ liệu

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ặc ienumerable<t> (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.

linq to datasets sự câu kết giữa linq và ado.net.
linq to xml truy vấn thông tin trong file xml.


2. tạo câu lệnh truy vấn

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.

Xem nhiều hơn: keen

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<car> cars  get  return new list<car>  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  ;   

2.1. cú pháp truy vấn

sử dụng cú pháp giống như bạn truy vấn cơ sở dữ liệu. mẫu cú pháp sẽ như sau:

var lists = from <biến lưu thông tin từng phần tử> in <nguồn dữ liệu> [<phép toán truy vấn: where, join ... in, order by...> biều thức lambda] select <biến lưu thông tin từng phần tử>

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.

2.2. cú pháp phương thức

là những phương thức mở rộng của ienumerable hoặc ienumerable<t>.

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<tsource> where<tsource>(this ienumerable<tsource> source, func<tsource, bool> 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<t> myquery<t>(this ienumerable<t> list, func<t, bool> 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.

3. thực thi truy vấn để lấy kết quả

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

linq- ngôn ngữ truy vấn tích hợp không thể không biết

sử dụng cách thực thi này sẽ giúp:

Xem nhiều hơn: Cách tắt hoàn toàn thông báo “Your Windows license will expire soon” trên Windows 10

+ cải thiện hiệu năng vì chỉ thực thi một lần.
+ dữ liệu trả về là mới nhất.

thực thi ngay lập tức (immediate execution): thực thi ngay lập tức câu lệnh và trả về kết quả. Để thực thi ngay lập tức, chúng ta có thể dùng những toán tử chuyển đổi như tolist, toarray, todictionary… hoặc những toán tử thành phần như first, firstordefault, last, lastordefault…

với ví dụ trên, chúng ta sửa code lại như sau để thực thi câu lệnh ngay lập tức:

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

4. lưu ý

sau khi tìm hiểu đến đây, mình đoán có nhiều bạn sẽ hỏi: tại sao không sử dụng for hoặc foreach liên minh if để truy vấn? hay linq hiệu năng như thế nào?

theo quan điểm cá nhân của mình thì việc sử dụng hay không sử dụng linq còn tùy thuộc vào quan điểm của mỗi người. mình thích dùng vì thấy dễ viết, ngắn gọn và dễ debug. về hiệu năng thì mặc dù linq có chậm hơn so với việc sử dụng for hoặc foreach nhưng với việc cấu hình máy tính, máy chủ khủng như hiện nay thì khoảng chậm đó cũng không ảnh hưởng lắm đến hiệu năng.

dưới đây mình có làm một phép so sánh giữa việc sử dụng for, foreach, linq các bạn hãy tham khảo nhé:

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<string> listguid)  var length = listguid.count; var count = 0; for (int i = 0; i < length; i++)  var item = listguid[i]; if (!item.contains(text)) continue; count++;  return count;  private static int findbyforeach(string text, ilist<string> listguid)  var count = 0; foreach (var item in listguid)  if (!item.contains(text)) continue; count++;  return count;  private static int findbylinq(string text, ilist<string> listguid)  var list = listguid.where(f => f.contains(text)); return list.count();  static ilist<string> randomlist()  var d = new list<string>(); for (int i = 0; i < 100000; i++)  d.add(guid.newguid().tostring());  return d;  

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

linq- ngôn ngữ truy vấn tích hợp không thể không biết

linq- ngôn ngữ truy vấn tích hợp không thể không biết

linq- ngôn ngữ truy vấn tích hợp không thể không biết

kết luận:

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é.

Nguồn gốc: https://danhgiaaz.com
danh mục: Kinh nghiệm – Hướng dẫn

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *