Ở 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).
Ý kiến bài viết