Hệ thống các lớp ADO.NET được chia thành hai dạng: các lớp kết nối (connected classes) và các lớp phi kết nối (disconnected classes) như hình dưới:
Trong phần này chúng ta sẽ tìm hiểu các lớp phi kết nối với hai lớp quan trọng nhất là DataTable và DataSet. Gọi chúng là các lớp phi kết nối vì chủ yếu làm việc với dữ liệu lưu trữ bộ nhớ trong và không cần kết nối đến Data Store (phải dùng đến các lớp kết nối hay các lớp nhà cung cấp (provider classes)). Các lớp phi kết nối được thực thi trong assembly System.Data.dll và thuộc namespace System.Data.
Lớp DataTable
Lớp DataTable thể hiện dữ liệu dạng bảng gồm các cột được tạo bởi lớp DataColumn và các hàng dữ liệu được thêm vào bảng bởi lớp DataRow. Đoạn mã sau minh hoạ cách tạo một bảng tên Students chứa thông tin về cách sinh viên như sau:
Mã VB
' Tạo một DataTable tên Students Dim students As New DataTable("Students")
Mã C#
// Tạo một DataTable tên Students DataTable students = new DataTable ("Students");
Đoạn mã trên tạo ra một bảng rỗng và có thuộc tính TableName được gán giá trị là Students.
Thêm cột hay tạo lược đồ (schema) cho bảng với lớp DataColumn
Một DataTable chỉ có ích khi nó có một lược đồ được tạo bằng đối tượng DataColumn và thiết lập một vài ràng buộc cho mỗi cột. Các ràng buộc này duy trì tính toàn vẹn dữ liệu bằng cách hạn chế dữ liệu nhập vào cột. Đoạn mã sau minh hoạ cách thêm các cột ID và Name vào bảng Students:
Mã VB
Dim id As New DataColumn("ID") id.DataType = GetType(Integer) id.Unique = True id.AllowDBNull = False students.Columns.Add(id) Dim name As New DataColumn("Name") name.DataType = GetType(String) name.MaxLength = 20; name.AllowDBNull = True students.Columns.Add(name)
Mã C#
DataColumn id = new DataColumn ("ID"); id.DataType = typeof (int); id.Unique = true; id.AllowNull = false; students.Columns.Add (id); DataColumn name = new DataColumn ("Name"); name.DataType = typeof (string); name.MaxLength = 20; name.AllowNull = true; students.Columns.Add (name);
Lớp DataColumn có một số thuộc tính sau:
Thuộc tính | Chức năng |
---|---|
DataType | Xác định kiểu dữ liệu cho cột. Mặc định là kiểu chuỗi (string). |
Unique | Xác định tính duy nhất cho giá trị của cột nếu gán giá trị true và ngược lại khi gán giá trị false. Mặc định là false. |
AllowNull | Cho phép giá trị của cột null khi gán giá trị true và ngược lại khi gán giá trị false. Mặc định là true. |
Caption | Tiêu đề cột. Mặc định là giá trị thuộc tính ColumnName được chuyển đến hàm constructor. |
MaxLength | Số kí tự tối đa của một chuỗi. Giá trị mặc định là -1. |
Khi đã tạo các cột, việc tiếp theo là xác định cột (hay nhóm cột) làm khoá chính (primary key) để xác định tính duy nhất cho mỗi hàng với thuộc tính PrimaryKey của DataTable. Thuộc tính PrimaryKey phải được gán đến một mảng các đối tượng DataColumn để chứa các khoá kết hợp. Đoạn mã sau minh hoạ cách lấy cột ID làm khoá chính cho bảng students:
Mã VB
students.PrimaryKey = new DataColumn(){id}
Mã C#
students.PrimaryKey = new DataColumn[]{id};
Thiết lập tăng giá trị (số) tự động cho cột khoá chính
Chúng ta có thể thiết lập chế độ tăng giá trị số tự động cho cột khoá chính bằng các thuộc tính AutoIncrement, AutoIncrementSeed, và AutoIncrementStep của đối tượng DataColumn như mô tả ở bảng dưới đây:
Thuộc tính | Chức năng |
---|---|
AutoIncrement | Cho phép giá trị số trong cột được tăng tự động mỗi khi một hàng mới được thêm vào bảng. |
AutoIncrementSeed | Giá trị của số đầu tiên muốn tăng tự động. Giá trị mặc định được khuyên là -1. |
AutoIncrementStep | Giá trị muốn tăng mỗi khi một hàng mới được thêm vào. Mặc định được khuyên là -1. |
* Giá trị của AutoIncrementSeed và AutoIncrementStep luôn luôn được gán đến giá trị -1 để tránh xung đột giá trị nhận được từ database server vì database không có số âm.
Thêm các hàng dữ liệu vào bảng với đối tượng DataRow
DataTable chứa thuộc tính Rows kiểu DataRowCollection chứa các đối tượng DataRow. DataRowCollection chứa phương thức Add với nhiều phiên bản (quá tải) có thể nhận tham số là một đối tượng DataRow, hay một mảng các đối tượng DataRow, hay các giá trị của một hàng. Bên cạnh Add, DataRowCollection còn chứa các phương thức sau:
Phương thức | Chức năng |
---|---|
ImportDataRow | Thêm một đối tượng DataRow đã được chỉnh sửa vào bảng và vẫn giữ nguyên các trạng thái và các thiết lập trước đó. |
Load | Cập nhật đối tượng DataRow hiện tại hay thêm đối tượng DataRow mới. |
LoadDataRow | Phát sinh một hàng với tham số là một mảng các đối tượng DataRow và một giá trị kiểu liệt kê LoadOption (với các thành phần chi tiết ở bảng dưới). |
Các thành phần hay thành viên của LoadOption (chú ý các khái niệm phiên bản (version) hay trạng thái (state) hàng sẽ được đề cập chi tiết ở các phần sau)
Thành viên | Chức năng |
---|---|
OverwriteChanges | Thay đổi phiên bản hàng hiện tại và phiên bản hàng gốc và thay đổi trạng thái hàng đến Unchanged. Hàng mới có trạng thái là Unchanged. |
PreserveChanges (mặc định) | Thay đổi phiên bản hàng gốc nhưng không thay đổi phiên bản hàng hiện tại. Hàng mới có trạng thái là Unchanged. |
Upsert | Thay đổi phiên bản hàng hiện tại nhưng không thay đổi phiên bản hàng gốc. Hàng mới có trạng thái là Added. Các hàng có trạng thái là Unchanged và phiên bản hàng hiện tại và hàng gốc giống nhau thì vẫn giữ nguyên là Unchanged, ngược lại nếu hai phiên bản khác nhau thì trạng thái đổi thành Modified. |
Đoạn mã sau minh hoạ cách thêm hàng mới vào bảng Students
Mã VB
'thêm hàng mới bằng cách tạo DataRow đầu tiên Dim newStudent As DataRow = student.NewRow() newStudent ("ID") = 123 newStudent ("Make") = "Minh" students.Rows.Add(newStudent) 'thêm hàng mới bằng cách chuyển giá trị trực tiếp students.Rows.Add(124, "Dung") 'Cập nhật lại student có ID là 124 bằng LoadDataRow students.LoadDataRow(new object() { 124, "Long"},LoadOption.OverwriteChanges)
Mã C#
//thêm hàng mới bằng cách tạo DataRow đầu tiên DataRow newStudent = student.NewRow(); newStudent ["ID"] = 123 ; newStudent ["Make"] = "Minh" ; students.Rows.Add(newStudent) ; //thêm hàng mới bằng cách chuyển giá trị trực tiếp students.Rows.Add(124, "Dung"); //Cập nhật lại student có ID là 124 bằng LoadDataRow students.LoadDataRow(new object[] { 124, "Long"},LoadOption.OverwriteChanges);
Xem trạng thái (state) của một đối tượng DataRow với DataRowState
Chúng ta có thể xem trạng thái hiện tại của một hàng với thuộc tính RowState có giá trị trả về là giá trị liệt kê DataRowState với các thành viên như sau:
Thành viên | Chức năng |
---|---|
Detached | Hàng được tạo nhưng không được thêm đến bảng |
Added | Hàng được tạo và được thêm đến bảng |
Unchanged | Hàng không thay đổi kể từ lần gọi cuối cùng phương thức AcceptChanges. Khi AcceptChanged được gọi, hàng sẽ chuyển đến trạng thái Unchanged. |
Modified | Hàng thay đổi kể từ lần gọi cuối cùng phương thức AcceptChanges. Thêm hàng hay cập nhật hàng sẽ thay đổi trạng thái hàng đến Added. Hàng chỉ thay đổi trạng thái đến Modified nếu trạng thái trước đó của hàng là Unchanged. |
Deleted | Một hàng bị xoá bởi phương thức Delete của DataRow hay phương thức DataTable.DeleteRow. |
Minh hoạ (mã VB) xem trạng thái hàng với thuộc tính RowState
Dim dr As DataRow = sv.NewRow() ' Rowstate: Detached Dim rs1 As String = String.Format("Rowstate 1:{0}", dr.RowState) dr("ID") = "1" 'Rowstate: Detached Dim rs2 As String = String.Format("Rowstate 2:{0}", dr.RowState) dr("Name") = "Peter" sv.Rows.Add(dr) ' Rowstate: Added Dim rs3 As String = String.Format("Rowstate 3:{0}", dr.RowState) sv.Rows.Add("2", "Messi") 'Rowstate: Added sv.AcceptChanges()'Rowstate: Unchanged Dim rs4 As String = String.Format("Rowstate 4:{0}", dr.RowState) dr("ID") = "3"'Rowstate: Modified Dim rs5 As String = String.Format("Rowstate 5:{0}", dr.RowState) sv.RejectChanges()'Rowstate: Unchanged Dim rs6 As String = String.Format("Rowstate 6:{0}", dr.RowState) dr.Delete()'Rowstate: Deleted Dim rs7 As String = String.Format("Rowstate 7:{0}", dr.RowState) Dim rs = rs1 + vbCrLf + rs2 + vbCrLf + rs3 + vbCrLf + rs4 + vbCrLf + rs5 + vbCrLf + rs6 + vbCrLf + rs7 + vbCrLf MsgBox(rs)
Kết quả
Quản lý các bản sao dữ liệu bằng DataRowVersion
Khi hàng dữ liệu trong bảng được tạo, bảng có thể nắm giữ các phiên bản hàng là giá trị kiểu liệt kê DataRowVersion với các thành viên sau:
Thành viên | Chức năng |
---|---|
Current | Giá trị hiện tại của hàng dữ liệu ngay cả sau khi các thay đổi được thực hiện. Phiên bản này tồn tại trong tất cả các trường hợp ngoại trừ khi DataRowState bị xoá. Khi DataRowState bị xoá, một ngoại lệ sẽ phát sinh. |
Default | Nếu DataRowState là Added hay Modified, phiên bản mặc định là Current. Nếu DataRowState bị xoá, một ngoại lệ sẽ phát sinh. Nếu phương thức BeginEdit đã được thực thi, phiên bản là Proposed. |
Original | Giá trị ban đầu được đưa vào hàng dữ liệu hay giá trị tại thời điểm phương thức AcceptChanges cuối cùng được thực thi. Phiên bản này không tồn tại cho đến khi DataRowState trở thành Modified, Unchanged, hay Deleted. Nếu DataRowState bị xoá, thông tin này có thể được nhận lại. Nếu DataRowState là Added, ngoại lệ VersionNotFound sẽ phát sinh. |
Proposed | Giá trị tại thời điểm chỉnh sửa (editing) dữ liệu hàng. Nếu DataRowState bị xoá, một ngoại lệ sẽ phát sinh. Nếu phương thức BeginEdit không được thực thi hay thực thi ngầm bằng cách chỉnh sửa dữ liệu trên hàng ở trạng thái Detached thì ngoại lệ VersionNotFound sẽ phát sinh. |
Đối tượng DataRow chứa phương thức HasVersion dùng để kiểm tra sự tồn tại của một phiên bản hàng dữ liệu cụ thể. Đoạn mã sau minh hoạ cách nhận thông tin về phiên bản của hàng dùng HasVersion và DataRowVersion:
Mã VB
Dim versionString As String For Each versionString In [Enum].GetNames(GetType(DataRowVersion)) Dim version As DataRowVersion = CType([Enum].Parse(GetType(DataRowVersion), versionString), DataRowVersion) If (row.HasVersion(version)) Then retVal += String.Format( "Version: {0} Value: {1}" + vbCrLf,version, row(columnName, version)) Else retVal += String.Format( "Version: {0} does not exist." + VbCrLf, version) End If Next
Mã C#
foreach (string versionString in Enum.GetNames(typeof (DataRowVersion))) { DataRowVersion version = (DataRowVersion)Enum.Parse( typeof(DataRowVersion),versionString); if (row.HasVersion(version)) { retVal += string.Format( "Version: {0} Value: {1} \r\n", version, row[columnName, version]); } else { retVal += string.Format( "Version: {0} does not exist.\r\n", version); } }
Một vài phương thức quan trọng
Khi làm việc với DataTable, bên cạnh phương thức Add, chúng ta cũng gặp một số phương thức quan trọng khác như AcceptChanges, RejectChanges, Delete, Copy, Clone. Chi tiết các phương thức có thể mô tả như bảng sau:
Phương thức | Chức năng |
---|---|
AcceptChanges | Thiết lập trạng thái hàng đến Unchanged. |
RejectChanges | Thiết lập trạng thái hàng đến trạng thái lần cuối cùng AcceptChanges được gọi. |
SetAdded | Thiết lập trạng thái hàng đến Added và sẽ bỏ qua phiên bản hàng Original. Phương thức chỉ thực thi khi đối tượng DataRow có trạng thái là Unchanges, ngược lại sẽ phát sinh ngoại lệ. Hữu ích khi giao tiếp giữa các data store khác nhau. |
SetModified | Thiết lập trạng thái hàng đến Modified và không thay đổi các phiên bản hàng Original hay Current. Phương thức chỉ thực thi khi đối tượng DataRow có trạng thái là Unchanges, ngược lại sẽ phát sinh ngoại lệ. Hữu ích khi giao tiếp giữa các data store khác nhau. |
Deleted | Thiết lập trạng thái hàng đến Deleted. |
Copy | Sao chép cả lược đồ và dữ liệu từ đối tượng DataTable. |
Clone | Chỉ sao chép lược đồ của đối tượng DataTable. |
ImportRow | Sao chép hàng dữ liệu từ một bảng đến một bảng khác có cùng lược đồ (schema). |
Minh hoạ dùng AcceptChanges và RejectChanges
Mã VB
students.Rows.Add("1", "Peter") students.Rows.Add("2", "Ronaldo") 'cập nhật các hàng mới st.AcceptChanges() students.Rows.Add("3", "Messi") 'từ chối thêm hàng mới st.RejectChanges()
Mã C#
students.Rows.Add("1", "Peter"); students.Rows.Add("2", "Ronaldo"); //cập nhật các hàng mới students.AcceptChanges(); students.Rows.Add("3", "Messi"); //từ chối thêm hàng mới students.RejectChanges();
Minh hoạ dùng Delete
Mã VB
students.Rows(1).Delete()'xoá hàng thứ hai
Mã C#
students.Rows(1).Delete(); //xoá hàng thứ hai
Minh hoạ dùng Copy
Mã VB
'sao chép dữ liệu và lược đồ từ bảng students đến bảng copyofStudentTable Dim copyofStudentTable As DataTable = students.Copy()
Mã C#
//sao chép dữ liệu và lược đồ từ bảng students đến bảng copyofStudentTable DataTable copyofStudentTable = students.Copy();
Minh hoạ dùng Clone và ImportRow
Mã VB
'sao chép lược đồ từ bảng students đến bảng cloneofStudentTable Dim cloneofStudentTable As DataTable = students.Clone() 'sao chép hàng thứ 3 của students đến cloneofStudentTable cloneofStudentTable.ImportRow(students.Rows(2))
Mã C#
//sao chép lược đồ từ bảng students đến bảng cloneofStudentTable DataTable cloneofStudentTable = students.Clone(); //sao chép hàng thứ 3 của students đến cloneofStudentTable cloneofStudentTable.ImportRow(students.Rows(2));
Sử dụng đối tượng DataView
Khi có các bảng dữ liệu (các đối tượng DataTable), chúng ta có thể sử dụng đối tượng DataView như là một cửa sổ để lưu trữ hay trích lọc dữ liệu từ bảng. Mỗi bảng có thể được gán nhiều DataView để xem dữ liệu theo những cách khác nhau mà không cần cập nhật đến database (như minh hoạ hình dưới).
Sắp xếp dữ liệu với thuộc tính Sort
Chúng ta có thể hiển thị dữ liệu từ bảng thông qua DataView theo thứ tự tăng dần (mặc định) hay giảm dần dựa vào một hay nhiều cột (cách nhau bởi dấu phẩy) bằng thuộc tính Sort của DataView. Sắp xếp tăng dần chúng ta dùng ASC và giảm dần dùng DESC. Đoạn mã sau sẽ minh hoạ cách chúng ta sắp xếp dữ liệu trong bảng Students thông qua một DataView (dv) theo thứ tự giảm dần dựa vào cột ID:
Mã VB
Dim dv As New DataView(students) ' tạo một DataView Dim i dv.Sort = "ID DESC" ' sắp giảm dần theo cột ID ' Hiển thị DataView For i = 0 To dv.Count - 1 lst_data.Items.Add(dv(i)("ID") & " " & dv(i)("Name")) Next
Mã C#
DataView dv = new DataView(students); // tạo một DataView int i; dv.Sort = "ID DESC"; // sắp giảm dần theo cột ID // Hiển thị DataView for (i = 0; i <= dv.Count - 1; i++) { lst_data.Items.Add(dv(i)("ID") + " " + dv(i)("Name")); }
Chúng ta cũng có thể sắp xếp theo nhiều cột ví dụ tăng dần theo cột ID và giảm dần theo Name như sau:
Mã VB
Dim dv As New DataView(students) ' tạo một DataView Dim i dv.Sort = "ID ASC, Name DESC" ' sắp tăng dần theo cột ID và giảm dần theo Name ' Hiển thị DataView For i = 0 To dv.Count - 1 lst_data.Items.Add(dv(i)("ID") & " " & dv(i)("Name")) Next
Mã C#
DataView dv = new DataView(students); // tạo một DataView int i; dv.Sort = "ID ASC, Name DESC"; // sắp tăng dần theo cột ID và giảm dần theo Name // Hiển thị DataView for (i = 0; i <= dv.Count - 1; i++) { lst_data.Items.Add(dv(i)("ID") + " " + dv(i)("Name")); }
Lọc dữ liệu với các thuộc tính RowFilter và RowStateFilter
Chúng ta có thể xem dữ liệu của DataTable bằng nhiều cách khác nhau với DataView thông qua các thuộc tính trích lọc dữ liệu RowFilter và RowStateFilter. Giá trị của RowFilter là một chuỗi giống lệnh WHERE trong ngôn ngữ truy vấn SQL nhưng không dùng từ “WHERE”. Đoạn mã sau minh hoạ cách dùng RowFilter để lọc ra những sinh viên có tên (Name) bắt đầu bằng chữ R trong bảng Students:
Mã VB
dv.RowFilter = "Name like 'R%'"
Mã C#
dv.RowFilter = "Name like 'R%'";
Bên cạnh dùng RowFilter, chúng ta có thể dùng RowStateFilter để lọc theo phiên bản (DataRowVersion) hay trạng thái hàng (DataRowState). RowStateFilter yêu cầu các giá trị là các thành viên của DataViewRowState (kiểu liệt kê):
Thành viên | Chức năng |
---|---|
Added | Nhận đối tượng DataRow có phiên bản Current và trạng thái là Added. |
CurrentRows | Nhận tất cả đối tượng DataRow có phiên bản Current. Tương đương các thành viên Added, ModifiedCurrent và Unchanged . |
Deleted | Nhận đối tượng DataRow có phiên bản Original và trạng thái là Deleted. |
ModifiedCurrent | Nhận đối tượng DataRow có phiên bản Current và trạng thái là Modified. |
ModifiedOriginal | Nhận đối tượng DataRow có phiên bản Original và trạng thái là Modified. |
None | Xoá thuộc tính RowStateFilter. |
OriginalRows | Nhận đối tượng DataRow có phiên bản Original. |
Unchanged | Nhận đối tượng DataRow có trạng thái là Unchanged. |
Đoạn mã sau minh hoạ lọc danh sách sinh viên trong bảng Students theo Name bắt đầu bằng chữ R và chỉ áp dụng cho những hàng có trạng thái là Deleted:
Mã VB
dv.RowFilter = "Name like 'R%'" dv.RowStateFilter = DataViewRowState.Deleted
Mã C#
dv.RowFilter = "Name like 'R%'"; dv.RowStateFilter = DataViewRowState.Deleted;
Di chuyển dữ liệu từ một DataView của một DataTable đến một DataTable khác
Để di chuyển dữ liệu từ một DataView của một DataTable đến một DataTable khác chúng ta dùng phương thức ToTable của DataView. Cú pháp phương thức ToTable:
VB
Public Function ToTable(tableName as String, distinct as Boolean, ParamArray columnNames() as String) as System.Data.DataTable
C#
DataTable DataView.ToTable(string tableName, bool distinct, params string[] columnNames)
Tham số tablename là tên bảng đích, distinct được gán đến true tức là chỉ lọc những giá trị không trùng nhau, và tham số cuối cùng là danh sách các cột được di chuyển đến bảng mới. Đoạn mã sau minh hoạ việc chuyển dữ liệu từ DataView dv từ bảng Students đến bảng mới tên MyStudents
Mã VB
Dim mystudents as DataTable = dv.ToTable( "MyStudents", true, "ID", "Name")
Mã C#
DataTable mystudents = dv.ToTable( "MyStudents", true, "ID", "Name");
Ý kiến bài viết