5. Sử dụng SqlDataAdapter, DataSet, DataTable

Ở bài trước bạn đã biết cách xử lý và hiện kết quả ra màn hình dùng Data Reader. Chú ý rằng : nếu chỉ muốn xem thông tin thì dùng Data Reader. Bài này hướng dẫn sử dụng DataSet để xử lý kết quả kết hợp với DataAdapter. Không giống với DataReader, tạo ra các đối tượng dùng interface System.DataIDataReader, thì DataSet là một thành phần đặc trưng của ADO.NET được sử dụng bởi tất cả các nhà cung cấp dữ liệu (data provider). Dataset có thể hoàn toàn độc lập và sử dụng khi kết nối hoặc ngắt kết nối khỏi nguồn. Mục đích cơ bản của DataSet là cung cấp xử lý xem xét dữ liệu lưu trữ trong một ‘memory cache’. Nếu như một DataSet không kết nối tới cơ sở dữ liệu thì làm sao mà xử lý dữ liệu và save lại vào database ? Đây là lí do mà DataAdapter ra đời. Hãy nghĩ DataAdapter chính là một chiếc cầu nối giữa DataSet và Data Source. Nếu không có một DataAdapter nào thì DataSet không thể truy cập bất cứ DataSource nào. DataAdapter đảm bào việc kết nối và truyền thông tin cho DataSet.

Tìm hiểu về ObjectModel

Đầu tiên thì mình đưa ra một số so sánh giữa DataSet và DataReader nhé, để các bạn tránh hay hỏi nhiều về việc : Lúc nào thì xài DataSet và lúc nào thì xài DataReader, giống và khác nhau như thế nào ?

So sánh DataSet và DataReader

Nếu bạn đơn giản chi muốn lấy dữ liệu và trình bày nó ra thôi thì dùng DataReader. Đặc biệt trường hợp mà bạn đọc với một số lượng lớn dữ liệu, ví như là vòng lặp tới hàng triệu dòng kết quả dữ liệu, bạn muốn tốc độ đọc nhanh và trình bày nhanh thì DataReader được sử dụng cho mục đích này, NHANH và TIỆN LỢI, cho việc ĐỌC dữ liệu.

Nếu bạn muốn chỉnh sử dữ liệu rồi update thông tin dữ liệu lại database thì bạn sử dụng DataSet. DataAdapter lấp đầy (fill) dữ liệu vào DataSet bằng cách sử dụng một DataReader, thêm vào đó resource cần được lưu trữ vào để sử dụng khi ngắt kết nối. Vì vậy việc sử dụng DataSet tốn nhiều tài nguyên hơn DataReader rất nhiều, bạn cần cân nhắc ở đây lúc nào sử dụng thành phần nào thì tốt, tránh lạm dụng quá. Nếu như bạn muốn đọc dữ liệu và viết ra dưới dạng XML, hoặc export database schema, viết lại db dưới dạng XML,…. thì nên sử dụng DataReader.

Giới thiệu sơ qua về DataSet

DataSet trong ADO.NET là một bước phát triển lớn trong việc phát triển ứng dụng cơ sở dữ liệu đa hệ. Khi lấy và chỉnh sửa dữ liệu, duy trì liên tục kết nối tới Data Source trong khi chờ user yêu cầu thì rõ ràng là tốn tài nguyên máy rất nhiều.

DataSet giúp ích ở đây rất lớn. Vì DataSet cho phép lưu trữ dữ liệu và chỉnh sửa tại ‘local cache’, hay gọi là offline mode. Có thể xem xét và xử lý thông tin trong khi ngắt kết nối. Sau khi chỉnh sửa và xem xong thì tạo một kết nối và update dữ liệu từ local vào Data Source.

Dữ liệu trong DataSet được lưu trữ dưới dạng một Collection các Tables và bạn cần phải xử lý thông qua các lớp DataTable -> DataRow và DataColumn.

Bảng dưới đây là kiến trúc DataSet.

Bạn chỉ cần tưởng tượng rằng : bạn có một cái bể nước (DataSource) , một cái máy bơm (DataAdapter) và một cái thùng đựng nước (DataSet). Thì khi lấy nước dùng cái bơm lấy nước từ bể, kiểm tra và lọc nước sau đó lại dùng cái bơm hút lại về cái bể nước. Đó chính là vai trò của cái bơm và DataAdapter tương tự như vậy.

Tương quan 3 lớp như thế này :

Có 4 cách tạo DataAdapter :


// Cách 1 : Đơn giản chỉ khai báo tạo đối tượng Adapter
SqlDataAdapter da = new SqlDataAdapter();
// Cách 2 : Thiết lập đối tượng SqlCommand
SqlDataAdapter da = new SqlDataAdapter(cmd);
// Cách 3 : Thiết lập query và đối tượng SqlConnection
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
// Cách 4 : Thiết lập query và mệnh lệnh thực thi
SqlDataAdapter da = new SqlDataAdapter(sql, connString);

Giới thiệu về DataTable và thành phần kèm

Nằm trong lớp : System.Data.DataTable. Có cấu trúc theo cấu trúc của bảng trong cơ sở dữ liệu gồm các hàng và cột nên có 2 thành phần kèm theo là : DataRow và DataColumn

DataRow sẽ là tập hợp các cột (record-set)

DataColumn là tập hợp các hàng cùng một đặc tính. (Field)


DataTable dt = new DataTable();
DataColumn col = dt.Columns[“Contact”]; // Cột Contact
DataColumn col = dt.Columns[2];
DataRow row = dt.Rows[2];

Làm việc với DataSet và DataAdapter

Tạo một dataset :


DataSet ds = new DataSet();
DataSet ds = new DataSet(“DataSet Name”);

Nếu bạn dùng cách 1 thì theo mặc định DataSet sẽ có tên là “NewDataSet”, cách thứ 2 là bạn đặt tên luôn cho DataSet bên trong constructor. Hoặc bạn có thẻ thay đổi tên của DataSet bằng thuộc tính ‘DataSetName’

Có nhiều cách xử lý với DataSet như:

· + Sử dụng thông qua Adapter

· + Đọc từ một tài liệu XML

Thử xử lý dữ liệu bằng một ví dụ :


using System;
using System.Data;
using System.Data.SqlClient;

namespace MSSQL_Server
{
class Database
{
static void Main(string[] args)
{
// Tạo connection strin
string connString = @"Server = NguyenVanThanh
Integrated Security = True;
Database = Demo
// Tạo SQL query
string sql = @"SELECT MaSV,TenSV FROM SinhVien";
// Tạo connection
SqlConnection conn = new SqlConnection(connString);
try
{
// Mỏ kết nối
conn.Open();
// Tạo Adapter
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
// Tạo DataSet
DataSet ds = new DataSet();
// Lấp đầy kết quả vào DataSet
da.Fill(ds, "sinhvien");
// Tạo DataTable thu kết quả từ bảng
DataTable dt = ds.Tables["sinhvien"];
// In kết quả ra Console
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn col in dt.Columns)
Console.WriteLine(row[col]);
Console.WriteLine("".PadLeft(20, '='));
}
}
catch (Exception e)
{
// Bắt lỗi
Console.WriteLine(e.Message);
}
finally
{
// Đóng kết nối
conn.Close();
}
}
}
}


Phân tích bài đơn giản ở trên nha.

Sau khi đã mở kết nối thì ta tạo một Adapter. Adapter này chứa thông tin về SQL query cần thực thi và một đối tượng kết nối conn, sau đó tạo một DataSet. Lúc này thì DataSet chưa có gì. Sau đó lấp đầy kết quả vào DataSet bằng method ‘Fill’ của Adapter. Từ đó hiểu thêm rằng : Adapter tự động thực thi câu lệnh SQL , thu lấy kết quả và gán hết vào DataSet. Khác với DataReader cần có một đối tượng SqlComnmand đễ xử lý. Nếu khi lấp đầy kết quả vào DataSet mà không gán tên bảng nào thì tự động trong DataSet tên lần lượt từng bảng là ‘TableN’ với bảng đầu tiên là Table, Table1,Table2…TableN.

Nếu một query được thực thi lại nhiều lần thì DataSet sẽ cập nhật thông tin từng đó bảng vào trong .

Chú ý trong Adapter ở trên nếu thay bằng cách tạo Adapter dưới đây :


SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand(sql, conn);

Thì kết quả thu được giống hệt nhau, không có gì thay đổi.

DataSet có thể chứa nhiều table vì thế khi xử lý Table nào cần phải gán vào DataTable một tên table cụ thể. Và cuối cùng dùng DataColumn và DataRow để xử lý DataTable đó. Đó là cách extract dữ liệu từ DataSet.

Các bạn có thể xem video sau để hiểu rõ hơn: download

17 nhận xét:

Nặc danh nói...

good!!!!Thank

Unknown nói...

cảm ơn bạn rất nhìu. bài viết rất hữu ích.

Nặc danh nói...

thank. bai viet rat hay

Nặc danh nói...

Cảm ơn! bài viết rất hay.
Cho mình hỏi là muốn cập nhật CSDL từ 1 DataSet có chứa nhiều DataTable thì làm thế nào? Mình đã thử dùng phương thức Update của Apdater nhưng nó chỉ cập nhật được mỗi cái DataTable đầu tiên của DataSet những cái còn lại thì ko cập nhật được.

Nặc danh nói...

I LOVE IT

Nặc danh nói...

good very

Nặc danh nói...

CÓ thể truyền được SqlDataAdapter vào hàm được không vậy bạn ???

Nặc danh nói...

rất cảm ơn bạn bài viết rất cụ thể và dễ hiểu............

DoanPQ nói...

Bài viết rất hay... cảm ơn nha

SQL_2012 nói...

Nhưng mình muốn update từ dataset vào CSDL thì làm sao nhỉ.
Mình sử dụng thuộc tính TableMappings mà hiểu sao cả. Mong ai đó có thể giúp mình với.
Mình cảm ơn nhiều nha!

Nặc danh nói...

jhj

Nặc danh nói...

bài viết này thật hay .cảm ơn bạn nhiều lắm

Nặc danh nói...

ừaetezgbfdxgb

Nặc danh nói...

bài viết hay thật, ví dụ rất dễ hiểu, sử dụng hình ảnh tượng trưng rất hay đó. cảm ơn bạn rất nhiều

Nguyễn Công Anh nói...

Thanks

Unknown nói...

Tks bạn

Nặc danh nói...

hj. bai viết rất dễ hiểu. cảm ở bạn rất nhiều :D