1. LINQ là gì ?
Để giảm gánh nặng thao tác trên nhiều ngôn ngữ khác nhau và cải thiện năng suất lập trình, Microsoft đã phát triển giải pháp tích hợp dữ liệu cho .NET Framework có tên gọi là LINQ (Language Integrated Query), đây là thư viện mở rộng cho các ngôn ngữ lập trình C# và Visual Basic.NET (có thể mở rộng cho các ngôn ngữ khác) cung cấp khả năng truy vấn trực tiếp dữ liệu Object, CSDL và XML.
LINQ là một tập hợp các thành phần mở rộng cho phép viết các câu truy vấn dữ liệu ngay trong một ngôn ngữ lập trình, như C# hoặc VB.NET.
LINQ là từ viết tắt của “Language-Integrated Query”
2. Tôi cần có gì để lập trình LINQ ?
LINQ có từ bản .NET 3.5, vậy nên tối thiểu chương trình của bạn phải chạy trên nền tảng này.
Visual Studio 2008, hoặc các phiên bản Express của nó là các bộ công cụ phát triển tiêu biểu cho ứng dụng dùng LINQ.
Tải về Visual Studio 2008 tại đây.
Tải về Visual Studio Express tại đây.
3. LINQ và ADO.NET khác nhau chỗ nào ?
Nôm na, LINQ là tập mở rộng cho phép viết các câu truy vấn ngay trong các ngôn ngữ lập trình. Nó cho phép bạn làm việc với các kiểu tập hợp dữ liệu, như XML, collection, array,… và cả CSDL.
ADO.NET là công nghệ cho phép các ứng dụng có thể kết nối và làm việc với các loại CSDL khác nhau (truy vấn, cập nhật, thêm, xóa, gọi thủ tục…).
Bản thân LINQ không phải là một công nghệ được tạo ra để thay thế ADO.NET, bạn có thể làm việc với LINQ mà không dính gì đến CSDL. Tuy nhiên, LINQ to SQL, là một phần mở rộng của LINQ, cho phép bạn có thể làm việc được với CSDL SQL Server, trong trường hợp này thì khi viết bạn có thể bỏ qua các câu lệnh ADO.NET mà chỉ quan tâm tới cú pháp mà LINQ cung cấp.
Nhớ rằng dù bạn không hề dùng đến ADO.NET khi viết chương trình sử dụng LINQ to SQL, nhưng đằng sau nó, ADO.NET vẫn được dùng để thực hiện kết nối, gửi các câu lệnh, các lời gọi thủ tục…
4. LINQ có hỗ trợ Unicode không ?
Có, LINQ là một thành phần của .NET, và như vậy, LINQ hỗ trợ Unicode một cách hoàn toàn tự nhiên, bạn có thể làm các thao tác chèn, sửa dữ liệu với tiếng Việt mà không cần cấu hình thêm. Tất nhiên, khi thiết kế CSDL, bạn vẫn phải chọn kiểu dữ liệu (NVARCHAR) và collation phù hợp để LINQ có thể làm việc một cách đúng đắn.
5. Tôi không thể tìm thấy một số phương thức (Add, RemoveAll…) như các ví dụ trong loạt bài “LINQ to SQL”
Kể từ bản RTM, các phương thức dùng cho thêm và xóa entity đã được đổi tên, cụ thể như sau:
- Add đổi thành InsertOnSubmit
- AddAll đổi thành InsertAllOnSubmit
- Remove đổi thành DeleteOnSubmit
- RemoveAll đổi thành DeleteAllOnSubmit
6. SQL và LINQ khác nhau thế nào?
SQL chỉ được dùng để truy vấn dữ liệu trong các CSDL dạng quan hệ, nếu muốn truy cập các dạng dữ liệu khác như HTML, XML v.v… thì đây là điều không thể đối với SQL và có thể đối với LINQ. Do đó có thể nói đây là 1 ưu điểm khác của LINQ mà SQL không có.
Ưa điểm của LINQ
Trước hết: tôi xin nói về quy luật cơ bản trong lập trình là dữ liệu phải nằm trong bộ nhớ chính. Do đó khi cần dữ liệu chúng ta phải dùng cách nào đó để đưa dữ liệu vào bộ nhớ (đọc text file, truy vấn từ database …). Trong môi trường .NET, dữ liệu trong bộ nhớ thường được thể hiện ở dạng các đối tượng và trước LINQ, chúng ta không có cách nào để móc nối các đối tượng hay thực hiện bất kỳ thao tác truy vấn nào. LINQ chính là giải pháp cho vấn đề này.
Thứ 2: Trước đây, cách phổ biến nhất để ứng dụng lấy dữ liệu từ các hệ cơ sở dữ liệu (CSDL) là sử dụng SQL (Structure Query Language – ngôn ngữ truy vấn cấu trúc). SQL có cú pháp rất khác với những ngôn ngữ lập trình phổ dụng như C# và VB.NET, do vậy bạn phải nhọc công “hàn gắn” hai thực thể khác biệt này với nhau trong mỗi dự án phần mềm. LINQ ra đời để giảm gánh nặng thao tác “hàn gắn” trên nhiều ngôn ngữ khác nhau.
Thứ 3: Một vấn đề khác với SQL là nó chỉ dùng để truy vấn dữ liệu trong các CSDL dạng quan hệ. Nếu muốn truy cập dữ liệu XML hay dạng khác (như trang HTML, email…), bạn lại phải sử dụng cú pháp truy vấn khác (XPath/XQuery). Cách giải quyết vấn đề tốt nhất hiện nay là LINQ
Thứ 4: Về vấn đề “Error” chúng ta không lập trình tương tác với CSDL tại cấp độ native language. Vì thế lỗi thường khó phát hiện rõ. Khó khăn trong việc quản lý lỗi xảy ra.
Thứ 5: Về vấn đề cú pháp truy vấn thì trước khi có LINQ chúng ta chưa có 1 cú pháp chung nào cho truy vấn dữ liệu từ những nguồn khác nhau. Với LINQ nó sẽ cung cấp cách duy nhất để truy cập dữ liệu từ bất kể nguồn dữ liệu nào với cú pháp giống nhau. Ngoài ra cách viết dễ dàng cho việc đọc và phân tích. Trường hợp này sẽ được thể hiện rõ ràng khi chúng ta cần lọc những dữ liệu với nhiều điều kiện phân cấp khác nhau thì LINQ sẽ thể hiện rõ tính ưu việt của mình. LINQ cũng cung cấp những bộ lọc, sắp xếp thứ tự, nhóm dữ liệu với khối lượng code tối thiểu nhưng vẫn bảo đảm tính rõ ràng.
7. Truy vấn LINQ
LINQ hỗ trợ loại dữ liệu IEnumerable . Những đối tượng hỗ trợ IEnumerable và IQueryable(T) được gọi là queryable.
3 phần của biểu thức LINQ
1. Có được các dữ liệu nguồn.
2. Tạo các truy vấn.
3. Thực hiện các truy vấn.
Ví dụ trong mã nguồn sau đây cho thấy ba phần của một truy vấn hoạt động như thế nào.
2. Tạo các truy vấn.
3. Thực hiện các truy vấn.
Ví dụ trong mã nguồn sau đây cho thấy ba phần của một truy vấn hoạt động như thế nào.
class IntroToLINQ { static void Main() { // The Three Parts of a LINQ Query: // 1. Data source. int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 }; // 2. Query creation. // numQuery is an IEnumerable var numQuery = from num in numbers where (num % 2) == 0 select num; // 3. Query execution. foreach (int num in numQuery) { Console.Write("{0,1} ", num); } } }
Minh họa sau đây cho thấy các hoạt động truy vấn. Trong LINQ việc thực hiện các truy vấn được thực hiện khi bạn truy cập dữ liệu.
Các nguồn dữ liệu.
Trong ví dụ trước vì dữ liệu là một mảng, nó hoàn toàn hỗ trợ đặc điểm chung giao diện IEnumerable. Điều này có nghĩa thực tế nó có thể được truy vấn với LINQ. Một truy vấn được thực hiện trong một câu lệnh foreach và foreach yêu cầu hỗ trợ IEnumerable hay IEnumerable(T). Loại có hỗ trợ IEnumerable(T) hoặc IQueryable(T) được gọi là queryable.
Trong ví dụ trước vì dữ liệu là một mảng, nó hoàn toàn hỗ trợ đặc điểm chung giao diện IEnumerable
Với LINQ to SQL, trước tiên bạn tạo một đối tượng quan hệ được ánh xạ vào lúc thiết kế bằng cách sử dụng trình thiết kế đối tượng quan hệ (O/R Designer) hoặc tự viết code. Viết các câu truy vấn dựa trên đối tượng và thi hành để LINQ to SQL xử lý việc giao tiếp với cơ sở dữ liệu. Trong ví dụ sau, Customer đại diện cho một bảng trong cơ sở dữ liệu, và Table hỗ trợ các đặc tính chung IQueryable.
// Create a data source from a SQL Server database. // using System.Data.Linq; DataContext db = new DataContext(@"c:\northwind\northwnd.mdf");
Truy vấn.
Truy vấn trong ví dụ trước trả về tất cả các số từ mảng số nguyên. Các biểu thức truy vấn chứa ba mệnh đề: from, where, select. (Nếu bạn đang quen với SQL sắp đặt của các mệnh đề là sai vị trí trong SQL). Mệnh đề from dùng để xác định nguồn dữ liệu, mệnh đề where dùng để lọc dữ liệu, mệnh đề select dùng để chọn ra những phần tử được trả về. Lúc này một điểm quan trọng là trong LINQ, các biến truy vấn chỉ chứa đựng thông tin truy vấn, là yêu cầu kết quả trả về khi câu truy vấn được thực hiện chứ nó không thực hiện việc truy vấn dữ liệu.
Truy vấn trong ví dụ trước trả về tất cả các số từ mảng số nguyên. Các biểu thức truy vấn chứa ba mệnh đề: from, where, select. (Nếu bạn đang quen với SQL sắp đặt của các mệnh đề là sai vị trí trong SQL). Mệnh đề from dùng để xác định nguồn dữ liệu, mệnh đề where dùng để lọc dữ liệu, mệnh đề select dùng để chọn ra những phần tử được trả về. Lúc này một điểm quan trọng là trong LINQ, các biến truy vấn chỉ chứa đựng thông tin truy vấn, là yêu cầu kết quả trả về khi câu truy vấn được thực hiện chứ nó không thực hiện việc truy vấn dữ liệu.
Thực thi truy vấn:
Cũng giống như trạng thái trước đây, biến truy vấn tự nó chỉ chứa các lệnh truy vấn. Việc truy vấn dữ liệu chỉ được thực hiện khi bạn truy cập đến dữ liệu trả về từ câu truy vấn:
foreach (int num in numQuery) { Console.Write("{0,1} ", num); }
Câu lệnh foreach là nơi các kết quả truy vấn được trả về. Bởi các biến truy vấn tự nó không bao giờ chứa kết quả truy vấn, bạn có thể sử dụng lại nó để bổ sung hoặc thực thi lấy dữ liệu tại một nơi khác.
8. Tách rời DataContext và các lớp thực thể vào các namespaces khác nhau
O / R Designer cung cấp cho các thuộc tính Context Namespace và Entity Namespace trên DataContext. Những thuộc tính này xác định tên của lớp DataContext và lớp các thực thể đã được tạo ra. Theo mặc định, các thuộc tính là rỗng, lớp DataContext và các lớp thực thể được đưa vào cùng một namesapce. Để đưa các lớp vào các namespace khác nhau, chúng ta có thể nhập giá trị vào trong thuộc tính Context Namespace và / hoặc Entity Namespace.
O / R Designer cung cấp cho các thuộc tính Context Namespace và Entity Namespace trên DataContext. Những thuộc tính này xác định tên của lớp DataContext và lớp các thực thể đã được tạo ra. Theo mặc định, các thuộc tính là rỗng, lớp DataContext và các lớp thực thể được đưa vào cùng một namesapce. Để đưa các lớp vào các namespace khác nhau, chúng ta có thể nhập giá trị vào trong thuộc tính Context Namespace và / hoặc Entity Namespace.