phần 1 chúng ta đã tìm hiểu cách tạo một bảng dữ liệu với đối tượng DataTable, DataColumn và DataRow. Chúng ta cũng tìm hiểu cách thức để xem dữ liệu từ một DataTable nhờ đối tượng DataView.

Trong phần 2 này chúng ta sẽ tìm hiểu cách thiết lập quan hệ giữa các DataTable khi chúng là thành phần của DataSet. Để hiểu kiến thức phần này, chúng ta cần hiểu một ít về cơ sở dữ liệu quan hệ.

Đối tượng DataSet

Các đối tượng DataTable sẽ độc lập, và vì thế mà không có ích cho các ứng dụng, nếu chúng không được đưa vào cùng một DataSet. Có thể xem một DataSet giống như một cơ sở dữ liệu quan hệ thu nhỏ (chứa các bảng và các quan hệ). Khi các bảng được đưa vào DataSet, chúng sẽ được thiết lập quan hệ (nếu có) nhờ đối tượng DataRelation (như hình dưới).

Để minh hoạ, giả sử chúng ta có hai bảng Genre (Thể loại) và Review (Tóm tắt) có mối quan hệ 1-n hay quan hệ cha (parent – bảng Genre) – con (child – bảng Review), nghĩa là một thể loại  (Pop hay Rock,…) sẽ có nhiều tóm tắt (review) khác nhau. Hai bảng có các cột như hình sau:

Việc tạo hai bảng Genre và Review là dễ dàng (xem lại phần 1) và để thiết lập mối quan hệ giữa hai bảng chúng ta cần đưa chúng vào một DataSet (gọi là musicDS). Đoạn mã sau minh hoạ cách tạo bảng, đưa bảng vào DataSet, và thiết lập quan hệ giữa các bảng:

Mã VB


' tạo một DataSet

Dim musicds As New DataSet("musicDS")

' Đưa bảng Genre vào DataSet

Dim gen As DataTable = musicds.Tables.Add("Genre")

' tạo thuộc tính và khoá chính cho bảng Genre

gen.Columns.Add("Id", GetType(String))

gen.Columns.Add("Name", GetType(String))

gen.PrimaryKey = New DataColumn() {gen.Columns("Id")}

' Đưa bảng Review vào DataSet

Dim review As DataTable = musicds.Tables.Add("Review")

' tạo thuộc tính và khoá chính cho bảng Review

review.Columns.Add("Id", GetType(String))

review.Columns.Add("Title", GetType(String))

review.Columns.Add("Summary", GetType(String))

review.Columns.Add("genId", GetType(String))

review.PrimaryKey = New DataColumn() {review.Columns("Id")}

' thiết lập quan hệ giữa bảng Genre và bảng Review

musicds.Relations.Add("gen_review", gen.Columns("Id"), review.Columns("genId"))

Mã C#


// tạo một DataSet

DataSet musicds = new DataSet("musicDS");

// Đưa bảng Genre vào DataSet

DataTable gen = musicds.Tables.Add("Genre");

// tạo thuộc tính và khoá chính cho bảng Genre

gen.Columns.Add("Id", typeof(string));

gen.Columns.Add("Name", typeof(string));

gen.PrimaryKey = new DataColumn[] { gen.Columns("Id") };

// Đưa bảng Review vào DataSet

DataTable review = musicds.Tables.Add("Review");

// tạo thuộc tính và khoá chính cho bảng Review

review.Columns.Add("Id", typeof(string));

review.Columns.Add("Title", typeof(string));

review.Columns.Add("Summary", typeof(string));

review.Columns.Add("genId", typeof(string));

review.PrimaryKey = new DataColumn[] { review.Columns("Id") };

// thiết lập quan hệ giữa bảng Genre và bảng Review

musicds.Relations.Add("gen_review", gen.Columns("Id"), review.Columns("genId"));

Khi đã thiết lập quan hệ giữa các bảng, chúng ta có thể dùng các phương thức GetChildRows() để lấy thông tin các hàng ở bảng con (Review) hay phương thức GetParentRow() để lấy thông tin hàng ở bảng cha (Genre). Đoạn mã sau minh hoạ việc dùng GetChildRows() và GetParentRow() để lấy thông tin hàng từ bảng Genre và các hàng tương ứng từ bảng con Review:

Mã VB


'Lấy thông tin các hàng từ bảng Review là con hàng đầu tiên bảng Genre

Dim childrows As DataRow() = gen.Rows(1).GetChildRows("gen_review")

' Lấy thông tin hàng Genre là cha của hàng đầu tiên bảng Review

Dim parentrow As DataRow = review.GetParentRow("vendors_parts")

Mã C#


//Lấy thông tin các hàng từ bảng Review là con hàng đầu tiên bảng //Genre

DataRow[] childrows = gen.Rows(1).GetChildRows("gen_review");

// Lấy thông tin hàng Genre là cha của hàng đầu tiên bảng Review

DataRow parentrow = review.GetParentRow("vendors_parts");

Thiết lập ràng buộc khoá chính (primary key) và ràng buộc khoá ngoại (foreign key)

Khi các bảng đã thiết lập quan hệ với DataRelation, chúng ta cần thêm các ràng buộc khoá chính và khoá ngoại để tạo sự nhất quán và toàn vẹn cho dữ liệu. Để tạo ràng buộc chúng ta chỉ cần chuyển giá trị true đến tham số thứ tư trong phương thức Add khi thiết lập quan hệ giữa hai bảng như sau:

Mã VB


musicds.Relations.Add("gen_review", gen.Columns("Id"), review.Columns("genId"),true)

Mã C#


musicds.Relations.Add("gen_review", gen.Columns("Id"), review.Columns("genId"),true);

Ràng buộc khoá ngoại

Ràng buộc khoá ngoại giúp duy trì tính toàn vẹn dữ liệu giữa các bảng, ví dụ khi chúng ta xoá một hàng trong bảng cha thì các hàng con tương ứng trong bảng con cũng phải được xoá. Chúng ta có thể thiết lập ràng buộc khoá ngoại đến bảng con (ví dụ Review) bằng ràng buộc ForeignKeyConstraint và Rule (kiểu liệt kê).

Có một số ràng buộc khoá ngoại cơ bản, là thành viên của Rule, sau:

Thành viên Chức năng
Cascade Là ràng buộc mặc định. Xoá hay cập nhật các hàng tương ứng ở bảng con khi hàng bảng cha bị xoá hay khoá ràng buộc unique của nó thay đổi.
None Phát sinh ngoại lệ InvalidConstrainException nếu hàng ở bảng cha bị xoá hay khoá ràng buộc unique của nó thay đổi.
SetDefault Thiết lập giá trị các cột khoá ngoại đến giá trị mặc định nếu hàng ở bảng cha bị xoá hay khoá ràng buộc unique của nó thay đổi.
SetNull Thiết lập giá trị các cột khoá ngoại đến giá trị DBNull nếu hàng ở bảng cha bị xoá hay khoá ràng buộc unique của nó thay đổi.

 

Minh hoạ thiết lập ràng buộc None cho bảng Review như sau:

Mã VB


Dim fk As ForeignKeyConstraint = review.Constraints("gen_review")

fk.DeleteRule = Rule.None

Mã C#


ForeignKeyConstraint fk = (ForeignKeyConstraint) review.Constraints("gen_review");

fk.DeleteRule = Rule.None;

Kết hợp các DataSet

Trong một vài trường hợp, chúng ta cần kết hợp dữ liệu từ các DataSet khác nhau. Để làm điều này, chúng ta sử dụng phương thức Merge của đối tượng DataSet (tìm hiểu thêm tại thư viện MSDN tại msdn.microsoft.com).