Thư viện ADO.NET chứa các lớp (trong namespace System.Data) dùng để trao đổi dữ liệu giữa các data stores (XML, databases,…) và các ứng dụng. Data stores rất đa dạng nên cần có các lớp trung gian để làm cầu nối giữa các lớp phi kết nối (disconnected classes) như dataset, datatable, datacolumn, datarow,…và một data store cụ thể.

Providers

Các lớp có nhiệm vụ di chuyển dữ liệu giữa các lớp phi kết nối (disconnected classes) và data store là các lớp kết nối (connected classes) hay các lớp nhà cung cấp (provider classes) (phần hình có viền đỏ ở trên). Microsoft .NET Framework chứa một vài provider như sau:

  • OleDb: chứa các lớp dùng để truy cập dữ liệu đến nhiều data stores như các phiên bản SQL Server 6.5 trở về trước, SyBase, DB2/400, và Microsoft Access.
  • Odbc: mục đích giống OleDb và chỉ được sử dụng khi chưa có provider mới hơn.
  • SQL Server: chứa các lớp truy cập đến SQL Server 7 trở về sau (các phiên bản SQL Server trước đó phải dùng OleDb).

Do chúng ta chủ yếu làm việc với SQL Server nên sẽ tập trung chủ yếu provider SQL Server. Ngoài ra, nếu muốn truy cập đến dữ liệu của các nhà cung cấp như Oracle, DB2, MySQL, chúng ta có thể đến website của các nhà cung cấp này để download các lớp cần thiết.

Microsoft .NET Framework cung cấp một tập các lớp provider được xem như là các lớp cơ sở (base classes) và khi chúng ta muốn kết nối đến nhà cung cấp nào thì chỉ việc tạo ra các lớp kế thừa tương ứng. Các lớp cơ sở thường bắt đầu bằng Db và các lớp cho nhà cung cấp nào thì sẽ thay Db bằng Sql hay Odbc hay OleDb tương ứng. Hình dưới là các lớp cơ sở và các lớp kế thừa cho nhà cung cấp SQL Server (chú ý cột thứ 3 là các interfaces của các lớp cơ sở):

Lớp DbConnection

Để kết nối đến dữ liệu từ các data stores, lớp quan trọng nhất là DbConnection. Đây là một lớp cơ sở trong .NET Framework và các lớp provider kế thừa từ nó như hình sau:

Mở và đóng kết nối

Để kết nối đến data stores, chúng ta cần tạo ra một chuỗi kết nối. Với chuỗi kết nối hợp lệ, chúng ta có thể mở (open) kết nối đến data source bằng phương thức open() và truy xuất dữ liệu. Khi hoàn thành công việc, chúng ta phải đóng (close) kết nối bằng phương thức close() để giải phóng tài nguyên.

Cấu hình chuỗi kết nối SQL Server

Chuỗi kết nối được cấu thành từ những từ khoá (và giá trị tương ứng) như mô tả ở bảng dưới đây:

Từ khoá Mô tả
Data    Source, Addr, Address, Network Address, Server Tên hay địa chỉ IP của database server (tối đa 128 kí tự). Mặc định là chuỗi rỗng.
Failover Partner Cung cấp sự hỗ trợ cho database mirroring (tối đa 128 kí tự). Mặc định là chuỗi rỗng.
AttachDbFilename,  extended properties, initial file name Đường dẫn tương đối hay đầy đủ đến tập tin chứa database cần kết nối (tối đa 260 kí tự). Đường dẫn có hỗ trợ từ khoá DataDirectory trỏ đến thư mục dữ liệu của ứng dụng. Database phải tồn tại trên một ổ đĩa cục bộ. Tên file log phải có định dạng <database-File_Name>_log.ldf, hoặc nó sẽ không được tìm thấy. Nếu file log không được tìm thấy, một file log mới sẽ được tạo ra. Mặc định là chuỗi rỗng.
Initial  Catalog, Database Tên của database cần kết nối. Mặc định là chuỗi rỗng.
Integrated Security,

Trusted_ Connection

Kết nối đến SQL Server bằng kết nối an toàn (secure connection) khi chứng thực qua tài khoản người dùng. Giá trị có thể là true, false, sspi. Mặc định là false.
Persist            Security Info, PersistSecurityInfo Trả về chuỗi kết nối với đầy đủ thông tin nếu thiết lập giá trị là true, ngược lại chuỗi kết nối sẽ không chứa thông tin bảo mật nếu thiết lập false. Mặc định là false.
User ID, Uid, User Tên người dùng để kết nối đến SQL Server khi không dùng một kết nối tin cậy (tối đa 128 kí tự).
Password, Pwd Mật khẩu dùng để đăng nhập đến SQL Server khi không dùng một kết nối tin cậy (tối đa 128 kí tự).
Enlist Khi thiết lập giá trị true, pool (danh sách các kết nối sẵn sàng cho một chuỗi kết nối ) sẽ đưa kết nối vào ngữ cảnh giao dịch đang diễn ra.
Pooling Khi thiết lập đến true sẽ phát sinh yêu cầu một kết nối mới lấy ra từ pool. Nếu pool không tồn tại, một pool mới sẽ được tạo. Mặc định là true.
Max Pool Size Số kết nối tối đa trong một pool. Mặc định là 100 kết nối.
Min Pool Size Số kết nối tối thiểu trong một pool. Mặc định là 0 kết nối.
Connection Reset Thiết lập lại kết nối database khi kết nối bị xoá từ pool. Mặc định là giá trị true.
MultipleActiveResultSets Khi thiết lập đến true, cho phép nhận nhiều tập kết quả chỉ đọc (read only) hay chỉ chuyển tiếp (forward only) trên cùng kết nối. Mặc định là false.
Replication Dùng bởi SQL Server cho việc sao chép. Mặc định là false.
Connect Timeout, Connection Timeout, Timeout Thời gian (tính bằng giây) chờ khi đang kết nối đến data store. Mặc định là 15 giây.
Encrypt Nếu Encrypt thiết lập đến true và SQL Server có một certificate (một đối tượng bảo mật chữ ký số) được cài đặt, tất cả các giao tiếp giữa client và server sẽ được mã hoá SSL. Mặc định là false.
Load   Balance Timeout, Connection Lifetime Thời gian (giây) tối đa để các kết nối trong pool tồn tại. Thời gian chỉ bắt đầu khi kết nối được trả đến pool. Mặc định là 0 (unlimited).
Network Library, Net, Network Cho phép dùng các thư viện mạng DLL khi kết nối đến SQL Server. Cho phép các thư viện bao gồm dbmssocn (TCP/IP),  dbnmpntw (Named Pipes), dbmsrpcn (Multiprotocol), dbmsadsn (Apple Talk), dbmsgnet (VIA), dbmsipcn (Shared Memory), và dbmsspxn (IPX/SPX). Mặc định là dbmssocn (TCP/IP), nhưng nếu một mạng không xác định và “.” hay “(local)” được xác định cho server, Named Pipes là mặc định.
Packet Size Số bytes cho mỗi packet gửi đến SQL Server. Giá trị hợp lệ trong khoảng 512 đến 32768. Mặc định là 8000 bytes.
Application Name, App Tên của ứng dụng (tối đa 80 kí tự). Nếu không thiết lập, mặc định là .NET SQL Client Data Provider.
Current Language, Language Xác định ngôn ngữ dùng cho các thông điệp cảnh báo hay lỗi của database server (tối đa 80 kí tự). Mặc định là chuỗi rỗng.
Workstation ID, Wsid Tên của máy client kết nối đến SQL Server (tối đa 128 kí tự). Mặc định là null.
Context Connection Dùng với SQLCLR. Khi thiết lập đến true, một kết nối đến SQL Server được thực thi. Mặc định là false.
Transaction Binding Liên kết kết nối các điều khiển với một giao dịch trong System.Transactions. Các giá trị hợp lệ là Implicit Unbind, Explicit Unbind. Mặc định là Implicit Unbind.
TrustServerCertifcate Khi thiết lập giá trị true, SSL được dùng để mã hoá kênh khi chứng thực. Mặc định là false.
Type System Version Xác định kiểu hệ thống mà ứng dụng mong đợi.
User Instance Khi thiết lập đến true sẽ bắt đầu một instance của SQL Express, dùng tài khoản người dùng hiện tại. Mặc định là false.

 

Ví dụ về chuỗi kết nối

Ví dụ 1: kết nối đến cơ sở dữ liệu tên Student trên máy tính cá nhân (localhost) bằng kết nối an toàn, không cần thông tin bảo mật, thời gian tối đa chờ kết nối là 30 giây (nếu vượt quá thì một ngoại lệ sẽ xuất hiện):


Persist Security Info=False; Integrated Security=SSPI; database=Student; server=localhost; Connect Timeout=30

Ví dụ 2: dùng thư viện TCP/IP (dbmssocn) để kết nối đến đến cơ sở dữ liệu Student trên máy tính có địa chỉ IP là 10.1.2.3, cổng 1433. Chứng thực dựa trên tài khoản có user name là ngocminh và pass là 123@abc:


Network Library=DBMSSOCN;Data Source=10.1.2.3,1433; InitialCatalog= Student;User ID= ngocminh; Password=123@abc

Kết nối đến tập tin cơ sở dữ liệu SQL cục bộ với SQL Express

Khi phát triển các ứng dụng nhỏ (hay dùng cho việc dạy và học), SQL Express là một lựa chọn phù hợp. SQL Express là một sản phẩm miễn phí dễ cài đặt và sử dụng, dựa trên công nghệ SQL Server và là một thành phần được cài mặc định trong Visual Studio .NET. Ví dụ chuỗi kết nối dùng để kết nối đến tập tin cơ sở dữ liệu cục bộ có phần mở rộng là mdf:


Data  Source=.\SQLEXPRESS;  AttachDbFilename=E:\Student.MDF; Integrated Security=True; User Instance=True;

Tập tin cơ sở dữ liệu là Student.mdf và lưu ý rằng phải tồn tại cả tập tin Student_LOG.ldf trong cùng ổ đĩa E. User Instance là true để tạo một instance SQL Express.

Chúng ta cũng có thể dùng từ khoá |DataDirectory| cho AttachDbFilename để sử dụng thư mục dữ liệu của ứng dụng, chuỗi kết nối trên có thể viết lại như sau:


Data  Source=.\SQLEXPRESS;  AttachDbFilename=|DataDirectory|\Student.MDF; Integrated Security=True; User Instance=True;

Lưu trữ chuỗi kết nối trong tập tin cấu hình ứng dụng (Application Configuration File)

Chúng ta có thể lưu trữ thuộc tính ConnectionString trong các tập tin cấu hình của máy (machine.config), ứng dụng windows (app.config), hay web ASP.NET (web.config), điều này sẽ giúp các chuỗi kết nối có thể được thay đổi mà không cần biên dịch lại ứng dụng.

Để lưu trữ chuỗi kết nối trong tập tin cấu hình ứng dụng (tập tin XML app.config), chúng ta đặt thẻ <connectionStrings> dưới thẻ <configuration>:


<configuration>

<connectionStrings>

.....

</connectionStrings>

....

</configuration>

Trong <connectionStrings> chúng ta có thể dùng các thẻ <add> (thêm chuỗi kết nối), <remove> (xoá một chuỗi kết nối), hay <clear> (xoá sạch các chuỗi kết nối).

Xét ví dụ lưu chuỗi kết nối trong tập tin cấu hình:


<configuration>

<connectionStrings>

<clear/>

<add Name="nw"

providerName = " System.Data.SqlClient "

connectionString = "Data Source=.\SQLEXPRESS;

AttachDbFilename=|DataDirectory|\Student.MDF; Integrated

Security=True; User Instance=True; "

/>

</connectionStrings>

....

</configuration>

Ví dụ trên dùng thẻ <clear> xoá sạch các chuỗi kết nối có trước đó đã được định nghĩa trong tập tin cấu hình máy và thêm một chuỗi kết nối mới (tên nw). Chuỗi kết nối được lưu trữ trong tập tin cấu hình có thể được truy cập bằng mã với collection ConnectionStrings trong lớp ConfigurationManager (thực thi trong assembly System.Configuration.dll), ví dụ truy cập nw như sau:

Mã VB:


'Lấy thông tin chuỗi nw từ tập tin cấu hình

Dim nw = ConfigurationManager.ConnectionStrings("nw")

'hiển thị tên chuỗi kết nối (nw)

Dim name = nw.Name

'tên provider (ở đây là System.Data.SqlClient)

Dim provider = nw.ProviderName

'lấy toàn bộ chuỗi kết nối và gán vào biến cnString

Dim cnString = nw.ConnectionString

'hiển thị chuỗi kết nối

MessageBox.Show("From App.Config: " & cnString)

Mã C#


//Lấy thông tin chuỗi nw từ tập tin cấu hình

var nw = ConfigurationManager.ConnectionStrings["nw"];

var connection = new SqlConnection(nw.ConnectionString);

//hiển thị tên chuỗi kết nối (nw)

var name = nw.Name;

//tên provider (ở đây là System.Data.SqlClient)

var provider = nw.ProviderName;

//lấy toàn bộ chuỗi kết nối và gán vào biến cnString

var cnString = nw.ConnectionString ;

//hiển thị chuỗi kết nối

MessageBox.Show("From App.Config: " + cnString);

Chúng ta có thể thực hiện mã hoá chuỗi kết nối khi giao tiếp với SQL Server bằng từ khoá Encrypt như ví dụ sau:


Data  Source=.\SQLEXPRESS;  AttachDbFilename=E:\Student.MDF; Integrated Security=True; User Instance=True; Encrypt = true

Danh sách kết nối (Connection Pooling)

Việc tạo một kết nối đến database là một nhiệm vụ tốn kém có thể làm chậm quá trình xử lý của ứng dụng. Một cách hiệu quả hơn là dùng danh sách kết nối (connection pooling – gọi tắt là pool) chứa các kết nối cho cùng một chuỗi kết nối. Nếu có nhiều chuỗi kết nối khác nhau sẽ có nhiều danh sách kết nối khác nhau.

Danh sách kết nối được kiểm soát bởi các từ khoá hay tham số trong chuỗi kết nối là: ConnectionTimeout, Min Pool Size, Max Pool Size, Pooling, Connection Reset, Load Balancing Timeout, và Enlist (xem bảng trên). Danh sách kết nối được duy trì bởi trình quản lý kết nối (connection manager).

Khi trình quản lý kết nối nhận một yêu cầu kết nối, nó sẽ kiểm tra pool chứa các kết nối sẵn sàng của chuỗi kết nối tương ứng và sẽ trả về một kết nối phù hợp nếu kết nối được tìm thấy. Nếu không tìm thấy kết nối nào và kích cỡ pool vẫn nhỏ hơn Max Pool Size, một kết nối mới được tạo, thêm vào pool, và kết nối này được dùng. Nếu không tìm thấy kết nối và kích cỡ pool bằng Max Pool Size, yêu cầu kết nối được chuyển đến hàng đợi chờ cho đến khi kết nối hợp lệ và trả về. Nếu thời gian chờ vượt quá ConnectionTimeout thì một ngoại lệ được phát sinh.

Một số lưu ý với pool

  • Chuỗi kết nối phải như nhau cho mọi người dùng hay dịch vụ tham gia trong một pool.
  • ID người dùng phải như nhau cho mọi người dùng hay dịch vụ tham gia trong pool.
  • Process ID cũng phải như nhau.
  • Connection pooling là công nghệ hướng client, nghĩa là nó được đặt trên máy gọi phương thức Open() của đối tượng DbConnection.
  • Connection pooling được tạo khi kết nối đầu tiên được mở. Khi kết nối đóng, nó sẽ trở lại pool và sẽ chờ cho đến khi một yêu cầu kết nối mới thực thi.
  • Kết nối sẽ được lấy ra từ pool khi được dùng và sẽ trả trở lại pool khi kết nối đóng. Mặc định, thời gian sống của một kết nối trong pool là 4 – 8 phút. Nếu muốn có ít nhất một kết nối trong pool, chúng ta thiết lập Min Pool Size >= 1.
  • Thời gian sống của kết nối trong pool phụ thuộc vào Load Balancing Timeout; số kết nối trong một pool phụ thuộc vào Min Pool SizeMax Pool Size; có thể bật (Pooling = true) hay tắt (Pooling = false) connection pooling; xoá sạch pool bằng phương thức ClearPool hay ClearAllPools trong lớp SqlConnection (hay OracleConnection) .