Một data reader là cách đơn giản nhất và nhanh nhất để chọn
một vài dữ liệu từ một nguồn cơ sơ dữ liệu, nhưng cũng ít tính năng nhất. Bạn có
thể truy xuất trực tiếp một đối tượng data reader – Một minh dụ được trả về từ
một đối tượng SqlCommand hoặc OleDbCommand từ việc gọi một phương thức ExecuteReader()
– có thể là một đối tượng SqlCommand, một đối tượng SqlDataReader, từ một đối tượng OleDbCommand là một OleDbDataReader.
– có thể là một đối tượng SqlCommand, một đối tượng SqlDataReader, từ một đối tượng OleDbCommand là một OleDbDataReader.
Mã lệnh sau đây sẽ chứng minh cách chọn dữ liệu từ bản Customers của cơ sở dữ liệu Northwind. Ví dụ kết nối với cơ sở dữ liệu chọn một số các
mẫu tin, duyệt qua các mẫu tin được chọn và xuất chúng ra màn hình console.
Ví dụ này có thể dùng cho OLE DB provider. Trong hầu hết các
trường hợp các phương thức của SqlClient đều được ánh xạ một
một vào các phương thức của đối OleDBClient.
Để thực thi lại các lệnh đối với một OLE DB data source, lớp OleDbCommand được sử dụng. Mã lệnh dưới đây là một ví dụ một
câu lệnh SQL đơn giảnvà đọc các mẫu tin được trả về bởi đối tượng OleDbDataReader.
Mã của ví dụ có thể được tìm thấy trong thư mục Chapter
09\03_DataReader.
Chú ý hai câu lệnh using dưới đây được
dùng trong lớp OleDb:
using System; using System.Data.OleDb;
Tất cả các trình cung cấp dữ liệu đều sẵn chứa bên trong các data
DLL, vì vậy chỉ cần tham chiếu đến System.Data.dll
assembly để dùng cho các lớp trong phần này:
public class DataReaderExample { public static void Main(string[] args) { string source = "Provider=SQLOLEDB;" + "server=(local)\\NetSDK;" + "uid=QSUser;pwd=QSPassword;" + "database=northwind"; string select = "SELECT ContactName,CompanyName FROM Customers"; OleDbConnection conn = new OleDbConnection(source); conn.Open(); OleDbCommand cmd = new OleDbCommand(select , conn); OleDbDataReader aReader = cmd.ExecuteReader(); while(aReader.Read()) Console.WriteLine("'{0}' from {1}" , aReader.GetString(0) , aReader.GetString(1)); aReader.Close(); conn.Close(); } }
Mã nguôn trên đây bao gồm các đoạn lệnh quen thuộc đã được trình
bày trong các chương trước. Để biên dịch ví dụ này, ta dùng các dòng lệnh
sau:
csc /t:exe /debug+ DataReaderExample.cs /r:System.Data.dll
Mã sau đây từ ví dụ trên cho phép tạo một kết nối OLE DB .NET, dựa
trên chuỗi kết nối:
OleDbConnection conn = new OleDbConnection(source); conn.Open(); OleDbCommand cmd = new OleDbCommand(select, conn);
Dòng thứ ba tạo một đối tượng OleDbCommand mới, dựa vào câu lệnh SELECT, kết nối sẽ thực thi câu lệnh lệnh này. Nếu bạn tạo
một command hợp lệ, bạn có thể thực thi chúng để trả về một minh dụ OleDbDataReader:
OleDbDataReader aReader = cmd.ExecuteReader();
Mội OleDbDataReader chỉ là một con trỏ
"connected" định trước. Mặt khác, bạn có thể chỉ duyệt qua các mẫu tin được trả
về, kết nối hiện tạo sẽ lưu giữ các mẫu tin đó cho đến khi data reader bị đóng
lại.
Lớp OleDbDataReader không thể tạo minh dụ
một cách trực tiếp – nó luôn được trả về thông qua việc gọi phương thức ExecuteReader() của lớp OleDbCommand. Nhưng bạn có thể mở một data reader, có một số
cách khác nhau để truy cập dữ liệu trong reader.
Khi một đối tượng OleDbDataReader bị đóng
lại (thông qua ciệc gọi phương thức Close(), hoặc một
đợt thu dọn rác), kết nối bên dưới có thể bị đóng lại thông qua một lời gọi
phương thức ExecuteReader(). Nếu bạn gọi ExecuteReader() và truyền CommandBehavior.CloseConnection, bạn có thể ép kết nối đóng
lại khi đóng reader.
Lớp OleDbDataReader có một bộ các quyền
truy xuất thông qua các mảng quen thuộc:
object o = aReader[0]; object o = aReader["CategoryID"];
Ở đây CategoryID là trường đầu tiên trong
câu lệnh SELECT của reader, cả hai dòng trên đều thực
hiện công việc giống nhau tuy nhiên cách hai hơi chậm hơn cách một – Tôi đã viết
một ứng dụng đơn giản để thực thi việc lập lại quá trình truy cập cho hàng triệu
lần một cột trong một mẫu tin reader, chỉ để lấy một vài mẫu. Tôi biết bạn hầu
như không bao giờ đọc một cột giống nhau hàng triệu lần, nhưng có thể là một số
lần, bạn nên viết mã để tối ưu quá trình đó.
Bạn có biết kết quả là thế nào không, việc truy cập môt triệu lần
bằng số thứ tự chỉ tốn có 0.09 giây, còn dùng chuỗi kí tự phải mất 0.63 giây. Lí
do của sự chậm trễ này là vì khi dùng chuỗi kí tự ta phải dò trong schema để lấy
ra số thứ tự của cột từ đó mới truy xuất được cơ sở dữ liệu. Nếu bạn biết được
các thông tin này bạn có thể viết mã truy xuất dữ liệu tốt hơn.
Vì vậy việc dùng chỉ số cột là cách dùng tốt nhất.
Hơn thế nữa, OleDbDataReader có một bộ
các phương thức type-safe có thể dùng để đọc các cột. Những phương thức này có
thể đọc hầu hết các loại dữ liệu như GetInt32, GetFloat, GetGuid, vân vân.
Thí nghiệm của tôi khi dùng GetInt32 là
0.06 giây. Nhanh hơn việc dùng chỉ số cột, vì khi đó bạn phải thực hiện
thao tác ép kiểu để đưa kiểu trả về kiểu integer. Vì vậy nếu biết trước schema
bạn nên dùng các chỉ số thay vì tên.
Chắc bạn cũng biết nên giữ sự cân bằng giữa tính dễ bảo trì và tốc
độ. Nếu bạn muốn dùng các chỉ mục, bạn nên định nghĩa các hằng số cho mỗi cột mà
bạn sẽ truy cập.
Ví dụ dưới đây giống như ví dụ ở trên nhưng thay vì sử dụng OLE DB
provider thì ở đây sử dụng SQL provider. Nhưng phần thay đổi của mã so với ví dụ
trên được tô đậm. Ví dụ này nằm trong thư mục 04_DataReaderSql:
using System; using System.Data.SqlClient; public class DataReaderSql { public static int Main(string[] args) { string source = "server=(local)\\NetSDK;" + "uid=QSUser;pwd=QSPassword;" + "database=northwind"; string select = "SELECT ContactName,CompanyName FROM Customers"; SqlConnection conn = new SqlConnection(source); conn.Open(); SqlCommand cmd = new SqlCommand(select , conn); SqlDataReader aReader = cmd.ExecuteReader(); while(aReader.Read()) Console.WriteLine("'{0}' from {1}" , aReader.GetString(0) , aReader.GetString(1)); aReader.Close(); conn.Close(); return 0; } }
Tôi đã chạy thử nghiệm của mình trên SQL provider, và kết quả là
0.13 giây cho một triệu lần truy cập bằng chỉ mục, và 0.65 giây nếu dùng chuỗi.
Bạn có mong rằng SQL Server provider nhanh hơn so với OleDb, tôi đã test thử nghiệm của mình trong phiên bản
.NET.
Nếu bạn có hứng thú chạy mã này trên máy tính của bạn thì nó
nằm trong các ví dụ 05_IndexerTestingOleDb và 06_IndexerTestingSql trong mã bạn đã down
về.