24/05/2018, 23:09

ADO.NET trên.NET Compact Framework

ADO.NET là tên chỉ một tập hợp các lớp truy cập cơ sở dữ liệu trong giới lập trình .NET. Tập hợp các lớp trong ADO.NET rất nhiều. Tuy nhiên, thao tác dữ liệu đơn giản và kết nối dữ liệu từ xa có thể thao tác được chỉ với một vài dòng ...

ADO.NET là tên chỉ một tập hợp các lớp truy cập cơ sở dữ liệu trong giới lập trình .NET. Tập hợp các lớp trong ADO.NET rất nhiều. Tuy nhiên, thao tác dữ liệu đơn giản và kết nối dữ liệu từ xa có thể thao tác được chỉ với một vài dòng lệnh. Trong phần này chúng ta tìm hiểu cách thức thao tác với dữ liệu cục bộ trên thiết bị.

DataSet
là các lớp framework cơ bản để thao tác dữ liệu cùng với .NET Compact Framework.
DataSet
có thể coi như là bộ máy cơ sở dữ liệu quan hệ trong chính nó. Nó lưu dữ các bảng trong bộ nhớ được sắp xếp như là các bảng, dòng, và cột và cho phép người phát triển thực hiện các thao tác cơ sở dữ liệu chuẩn, như thêm và xóa dữ liệu, sắp xếp, và kiểm tra ràng buộc.

Các nhà phát triển là những người hiểu làm thế nào để làm việc có hiệu quả với

DataSet 
trên .NET Compact Framework sẽ ghi hiệu quả các ứng dụng ADO.NET trên framework.

Để thao tác dữ liệu trong lập tình ADO.NET được đổ vào

DataSet
từ CSDL lớn, làm việc với các khoang dữ liệu trong
DataSet
, và ghi dữ liệu thay đổi trở lại CSDL. Trong phần này chúng ta tìm hiểu làm thế nào để đổ dữ liệu vào
DataSet
bằng cách trèn dữ liệu chương trình và thực hiện thao tác đơn giản trên dữ liệu.

Bên trong DataSet: DataTables, DataRows, và DataColumns

DataSet 
chứa một hoặc nhiều
 DataTables
. Mỗi
DataTables
tương ứng với một bảng trong CSDL quan hệ. Nó có một tập hợp các
DataRows
, và mỗt
DataRow
có một tập hợp
DataColumns
trên thực tế lưu trữ dữ liệu. Để tạo
DataSet, DataTables
, và
DataColumns
rất đơn giản. Hình 4.1 mô hình kiến trúc tổng quan cách một
DataSet
lưu trữ dữ liệu đơn giản phonebook.

Miêu tả DataSet cấu trúc của phone book.

Chúng ta có thể sử dụng riêng một

DataTable
để lưu trữ dữ liệu liên quan cùng với một bảng, nhưng
 DataSet
cung cấp các phương thức và thuộc tính có tiện ích thêm và thực sự tạo một CSDL quan hệ thu nhỏ trong bộ nhớ. Ví dụ, cùng với
DataSet
chúng ta có thê làm việc tất cả các cái sau:

 Thao tác với thông tin bên trong một

DataSet
như là một CSDL quan hệ nhở. Ví dụ, chúng ta có thể thiết lập mối quan hệ cha con, cập nhật, xóa, và tạo cột dữ liệu được tính toán từ các trường dữ liệu khác

 Ghi và lạp nội dung của tất cả

DataTables
vào một file XML cùng với chỉ một dòng lệnh.

 Thông qua bộ máy SQL CE, bộ máy này sẽ giúp chúng ta đưa vào nó các bảng từ CSDL quan hệ được lưu trữ trên thiết bị hoặc thay thế bằng dữ liệu từ máy chủ ở xa.

 Thông qua nó SQL cung cấp được đưa vào các bảng từ máy chủ ở xa.

 Nhận một phần của

DataSet
, cái mà trả về giá trị của dịch vụ Web, hoặc thông qua
DataSet
trở lại dịch vụ Web.

Trong phần này chúng ta sẽ tìm hiểu cách thao tác dữ liệu trên

DataSet
.

Đưa dữ liệu vào DataSet

Để đưa dữ liệu vào một

DataSet
, chúng ta làm theo các bước sau:

c1: Nhận một thao tác

DataTable
với
DataSet
mà chúng ta muốn thêm một dòng mới vào. Nếu cần thiết, tạo một
DataTable
mới. Tập hợp các
DataTables
DataSet
quản lý có thể được sử dụng thông qua thuộc tính
DataSet.Tables
. Nếu chúng ta phải tạo một
DataTable
mới và thêm nó vào tập hợp
DataSet.Table
, sao đó thông thường chúng ta thêm dữ liệu vào bảng đã tồn tại, vì vậy chúng ta có thể bỏ qua các bước này:

Tạo một

DataTable
thông qua cấu trúc
DataTable
.

Tạo một

DataColumns 
và thêm vào nó tập hợp
DataTable.Columns
. Mỗi
DataColumn
, chúng ta phải chỉ ra tên, kiểu dữ liệu của cột.

Thêm

DataTable
vào tập hợp
DataSet.Tables
bằng cách gọi phương thức .
Add
.

c 2: Tạo một

DataRow.
Ví dụ, tạo một dòng mới cho
DataTable
đầu tiên trong
DataSet
:

Sử dụng

l_newRow = l_DataSet. Tables[0].NewRow.
Chúng ta có thể chỉ ra ra bảng thông qua tên bảng:

Ví dụ

_newRow = l_DataSet.Tables["Customers"].NewRow

c 3:

DataRow
mới tự động được tạo cùng với các cột vào tương ứng với bảng đã

được tạo. Trèn giá trị vào các cột của

DataRow
.

c 4: Thêm

DataRow
mới vào tập hợp Rows của
DataTable
đã được tạo:

Ví dụ

_DataSet.Tables[0].Rows.Add(l_newRow
)
;
.

c5: Sau khi chúng ta đã thêm vào tất cả các dòng như mong muốn, gọi phương thức

DataSet.AcceptChanges
để đồng ý tất cả sự thay đổi. Để hủy bỏ tất cả việc thêm mới dữ liệu chúng ta gọi phương thức
DataSet.RejectChanges.

Xây dựng một DataSet lưu trữ một Phone Book

Để mô tả cách tạo một

 DataSet
có khả năng lưu trữ dữ liệu quan hệ, chúng ta hãy xem

xét ví dụ ứng dụng PhoneBook. Trong ứng dụng ví dụ này, chúng ta hãy xem xét khả năng của một

DataSet
lưu trữ phone book.
DataSet
lưu trữ một bảng
DataTable
, bảng này được thiết lập gồm hai
DataColumns
, cột thứ nhất lưu trữ tên và cột thứ hai lưu trữ số điện thoại. Đoạn mã sau mô tả năm bước cần thiết để thêm dữ liệu vào một
DataSet
, bao gồm tạo một bảng mới.

Listing 4.1 Tạo và lưu trữ một

DataSet
DataSetl_DataSet = new DataSet(); 
// Create a DataTable that holds a "Name" and a "PhoneNumber"
 DataTablel_newTable = new DataTable("Phone Contacts");
l_newTable.Columns.Add(new DataColumn("Name", typeof(System.String)));
l_newTable.Columns.Add(new DataColumn("PhoneNumber",
typeof(System.String)));
// Add the DataTable to the DataSet's table collection l_DataSet.Tables.Add(l_newTable); 
// Now put a few names in...
// GEORGE WASHINGTON
DataRow l_newRow = l_DataSet.Tables[0].NewRow();
l_newRow[0] = "George Washington"; l_newRow[1] = "555 340-1776"; 
l_DataSet.Tables[0].Rows.Add(l_newRow); 
// BEN FRANKLIN
l_newRow = l_DataSet.Tables[0].NewRow(); l_newRow["Name"] = "Ben Franklin";
l_newRow["PhoneNumber"] = "555 336-3211";
l_DataSet.Tables[0].Rows.Add(l_newRow); 
// Commit the changes l_DataSet.AcceptChanges();
    

Trích dữ liệu từ một DataSet

Trích dữ liệu từ một

DataSet
như là truy nhập
DataTable
trong tập hợp
DataSet.Tables
và tìm kiếm dòng mong muốn trong bảng. Mỗi dòng có một chỉ số, tạo cho nó dễ dàng truy cập cột mong muốn. Chỉ số đầu tiên là 0, như trong ví dụ:

l_DataSet.Tables[0].Rows[0][0]
Truy nhập cột đầu tiền trong dòng đầu tiên của
DataTable
đầu tiên.

l_DataSet.Tables[0].Rows[0][9]
truy nhập cột thứ 10 trong dòng đầu tiên của
DataTable
đầu tiền.

l_DataSet.Tables[0].Rows[29][9]
Truy nhập cột thứ 10 trong dòng 30 của
DataTable
đầu tiền.

Trích dữ l i u PhoneBook từ m ột DataSet

Sau đây là đoạn mã trong ứng dụng ví dụ PhoneBook. Nó tìm kiếm thông qua tất cả các dòng trong

DataTable
đầu tiên trong một
DataSet
và đưa giá trị cột thứ 0 và thứ 1 vào một ListBox:
for (int i = 0; i < phonebookEntriesDataSet.Tables[0].Rows.Count; i++)
{    
this.listBox1.Items.Add( phonebookEntriesDataSet.Tables[0].Rows[i][0] 
+ "" + phonebookEntriesDataSet.Tables[0].Rows[i][1]);
}

Thay đổi dữ liệu trong một DataSet

Để thay đổi dữ liệu trong

DataSet
, truy cập vào
DataColumn
mà chúng ta muốn thay đổi và thiết lập giá trị mới. Khi tất cả thay đổi đã kết thúc, gọi
AcceptChanges
để xác nhận sự thay đổi.

Ví dụ, đoạn mã sau thiết lập cột thứ 2 trong dòng đầu tiên của bảng đầu tiên trong tập hợp

DataSet
thành một số ngâu nghiện được cung cấp bởi
randomGenerator, randomGenerator 
được cung cấp trong lớp Random.
// Column 1 is the phone number.
    //|
    //V
    m_phonebookDS.Tables[0].Rows[0][1] = randomGenerator.Next().ToString();
    

Thay đổi bằng cách sử dụng chỉ số tên, cách này sẽ chậm hơn trong .NET Compact Framework khi lượng lớn dữ liệu phức tạp:

m_phonebookDS.Tables["Phone Contacts"].Rows[0]["PhoneNumber"] = l_randomGenerator.Next().ToString();
    

DataSet
cho phép chúng ta chỉ ra qui tắc riêng biệt, mà dữ liệu trong tập hợp
DataSet.Tables
phải theo. Lớp cơ sở
Constraint
chỉ rõ qui tắc mà dữ liệu trong
DataTable
phải theo.

ForeignKeyConstraint
thường được sử dụng để tạo sức mạnh cho hành vi khi thay đổi hoặc xóa cột khóa chính trong một bảng. Bởi vì
ForeignKeyConstraint
được mong đợi để sử dụng trong mô hình quan hệ cha con giữa các bảng.

Thêm ràng buộc vào một DataSet

Mỗi

DataTable
lưu trữ trong tập hợp
DataSet.Tables
lưu trữ
ConstraintCollection 
trong thuộc tính
Constraints
. Vsi dụ, để truy cập
ConstraintCollection
trong bảng đầu tiên của một
DataSet
, sử dụng như sau:

m_phonebookDS.Tables[0].Constraints

Các bước để tạo và khởi tạo ràng buộc:

c 1: Thêm ràng buộc vào tập hợp

Constraints
của bảng thíc hợp.

c 2: Thiết lập cờ

DataSet.EnforceConstraints
thành true để bật yêu cầu ràng buộc. Khi chúng ta thiết lập cờ thành true, mỗi ràng buộc trong mỗi tập hợp
DataTable.Constraints
được chọn, và đưa ra một ngoại lệ nếu kiểm tra bị lỗi.

Thêm một UniqueConstraint

Để thêm một

UniqueConstraint
vào một
DataSet
, làm theo các bước sau:

c 1: Tạo một

UniqueConstraint
bằng cách sử dụng một trong bốn khởi tạo trên .NET Compact Framework:

UniqueConstraint(String name, DataColumn col)
Creates a
UniqueConstraint 
with specified name that enforces uniqueness on a single
DataColumn.

UniqueConstraint(DataColumn col)
Creates a
UniqueConstraint
that enforces uniqueness on a single
DataColumn
.

UniqueConstraint(String name, DataColumn[] cols)
Creates a
UniqueConstraint
that enforces uniqueness for multiple columns in a row. The columns are specified by passing them as an array.

UniqueConstraint(DataColumn[] cols) 
Same as above except the
UniqueConstraint
is nameless.

UniqueConstraint(String name, string[] colNames, bool isPrimaryKey)
This fifth public constructor is useful only to the Smart Device Extensions environment.

Bước 2: Thêm

UniqueConstraint
vào tập hợp Constraints của
DataTable 
mong muốn

c 3: Thiết lập

DataSet.EnforceConstraints
thành true để bật sự ràng buộc..

Ví dụ:

// Add a UniqueConstraint to the phone number column
    // Note: Using indexing by the string "PhoneNumber" is slower
    UniqueConstraint l_UniqueConstraint = new
    UniqueConstraint(l_DataSet.Tables[0].
Columns["PhoneNumber"]);
    l_DataSet.Tables[0].Constraints.Add(l_UniqueConstraint);
    

Ngăn ngừa giá trị NULL trong DataColumn

Thuộc tính

DataColumn.AllowDBNull
rất hữu ích để không cho phép một
DataColumn 
có giá trị
DBNull
. Nếu chúng ta tạo một
DataRow
mới và không đưa một giá trị vào một cột, nó nhận giá trị mặc định là
 DBNull
.

Ví dụ:

l_newTable.Columns["Name"].AllowDBNull = false;
    

Nếu DataColumn có

AllowDBNull
false
được thiết lập thành
DBNull
, ngoại lệ
System.Data.NoNullAllowed
được đưa ra khi một dòng mới được thêm vào DataTable trong
DataSet
. Ví dụ:
DataRow l_newRow = m_phonebookDS.Tables[0].NewRow();
    l_newRow[0] = "Violator"
    l_newRow[1] = "5555587";
    // This is going to throw an exception because the "Name"
    // DataColumn was never set, so it is DBNull, and that is
    // not allowed for the DataColumn m_phonebookDS.Tables[0].Rows.Add(l_newRow);]
    

Khi một dòng được thêm vào

DataTable
, dòng rỗng được tạo bằng cách gọi
DataTable.NewRow
. Một
DataTable
biết giản đồ cho một dòng, dòng này phải được tạo và thể hiện dòng mới tương ứng với giản đồ. Có nghĩa là dòng mới lưu trữ phải có
 DataColumns
cùng với kiểu dữ liệu đúng với cái mà chúng ta đã thiết lập.

Thuộc tính

DataColumn.AutoIncrement
có thể được thiết lập trong
DataTable
là một
DataColumn
có giá trị tự động tăng khi một dòng mới được tạo. Nó rất hữu dụng khi làm trường khóa.

Có ba thuộc tính quan trong trong

 DataColumn
liên quan đến trường tự động tăng giá trị:

DataColumn.AutoIncrement
Thiết lập giá trị true cho DataColumn tự động tăng.
DataColumn.AutoIncrementSeed
Giá trị bắt đầu cho giá tự động tăng.
DataColumn.AutoIncrementStep
Giá trị của bước nhảy cho mỗi giá trị mới.

Nếu

DataColumn
là một cột tính tóan, sau đó cố gắng thiết lập như là một cột tự động tăng sẽ nguyên nhân một
ArgumentException
.

Nếu kiểu dữ liệu của

DataColumn
không phải là
Int16, Int32,
hoặc
Int64
, sau đó nó bị ép kiểu thành
Int32
. Nó có thể là nguyên nhân mất dữ liệu, nếu
DataColumn
là kiểu số thực. Nếu
DataColumn
là kiểu chuỗi, thiết lập cột đó tự động tăng giá trị sẽ ép kiểu dữ liệu của cột này thành kiểu integer.

Ví dụ tạo một trư ng có giá t r tự động tăng:

Thiết lập một trường có giá trị tự động tăng từ 10, bước nhảy có giá trị là 5.

l_newTable.Columns["ContactID"].AutoIncrement = true; 
l_newTable.Columns["ContactID"].AutoIncrementSeed = 10; 
l_newTable.Columns["ContactID"].AutoIncrementStep = 5;
    

Chúng ta hãy tìm hiểu

DataSet
lưu trữ
DataTable
, truy nhập dữ liệu, và yêu cầu theo mẫu ràng buộc trên dữ liệu. Trong phần này chúng ta xây dựng kiến thức và học các thao tác nền tảng chung nhất về CSDL quan hệ cùng với dữ liệu bên trong
DataSet
.

X uất phát từ giá t r

DataColumn
cùng với bi u thức và t r ư ng tính toán

Giá trị của

DataColumn
có thể được tính toán dựa trên giá trị của DataColumn khác trong cùng một
DataRow
. Để làm điều này, sử dụng thuộc tính DataColumn.Expression để mô tả giá trị tính toán của
DataColumn
. Thuộc tính
Expression
là một giá trị chuỗi được mô tả sự tính toán xuất phát từ giá trị cho
DataColumn
.

Cú pháp biểu thức rất nhiều và hỗ trợ rất nhiều phép tính toán học và chuỗi. Bảng 4.1 đưa đến tất cả các phép toán được .NET Compact Framework hỗ trợ.

Bảng 4.1. Các phép toán Framework hỗ trợ để tính toán

Ví dụ:

l_newTable.Columns["FullName"].Expression = "FirstName + ' ' + LastName";
    l_newTable.Columns["TotalPrice"].Expression = "MSRP - Discount";
    l_newTable.Columns["FinalGrade"].Expression = "Avg(Exam1, Exam2, Exam3)";
    

Biểu thức quan hệ cha con trong

DataSet

Thực chất thành phần của CSDL quan hệ là các bảng với các dòng có khả năng tạo quan hệ cha con, hoặc một quan hệ, giữa hai bảng. Một quan hệ giưa hai bảng được tạo bằng liên kết giưa hai bảng bằng một hoặc nhiều cột dữ liệu gọi là khóa chính. Trong bảng cha, khóa chính xác định mỗi dòng là duy nhất trong bảng. Các dòng trong bảng con có một trường gọi là khóa ngoại, trường này không phải là duy nhất trong bảng con.

Ví dụ bảng cha

MainContactTable
, và bảng con
CholesterolTable
. Bảng 4.2. MainContactTable Bảng 4.3 CholesterolTable

Trong bảng

CholesterolTable, CustID
tham chiếu đến một bản ghi duy nhất trong bảng
MainContactTable
. Bảng 4.4 và 4.5 cho thấy quan hệ cha con khi lưu trữ. Bảng 4.4. MainContactTable Bảng 4.5 CholesterolTable

Trong ví dụ bảng cha con ví dụ trên, bản ghi trong bảng

CholesterolTable
tương ứng với George Washington và một bản ghi tương ứng với Ben Franklin. Vấn đề gì sẽ xây ra nếu bản ghi George Washington bị xóa trong bảng
MainContactTable
? Hệ thống sẽ bị xóa tất cả bản ghi tương ứng trong bảng
CholesterolTable
, hoặc CSDL sẽ ở trạng thái lỗi.

.NET Compact Framework cung cấp hai lớp có thể làm việc đó tự động:

DataRelation
ForeignKeyConstraint
.

Tạo một

DataRelation
để thể h i ện quan hệ cha con

Khi thiết lập một

DataRelation
giữa hai bảng, chúng ta chỉ rõ
DataColumn
như là khóa chính và khóa ngoại. Sau khi
DataRelation
được tạo, nó sẽ đảm bảo rằng dữ liệu quan hệ của
DataSet
như là được mô tả bởi
DataRelation.
Ví dụ, nếu chúng ta xóa bản ghi đầu tiên trong bảng
MainContactTable
,
DataRelation
sẽ tự động xóa tất cả các dòng con trong bảng
CholesterolTable
.

Để thiết lập

DataRelation
giữa hai bảng trong một
DataSet
, trước tiên tạo
DataRelation
bằng cách sử dụng hàm khởi tạo thông qua
DataColumns
bao gồm khóa chính và khóa ngoại. Các hàm khởi tạo .NET Compact Framework như sau:

DataRelation(String relName, DataColumn parent, DataColumn child) 
Tạo một
DataRelation
giữa
 DataColumns
cha và con.

DataRelation(String relName, DataColumn[] parent, DataColumn[] child) 
Tạo
DataRelation
giữa hai bảng sử dụng nhiều trường cho mỗi bảng đê quan hệ.

DataRelation(String relName, DataColumn parent, DataColumn child, bool createConstraints)
Tạo một
DataRelation
giữa
DataColumns
cha và con.

DataRelation(string relName, DataColumn[] parent, DataColumn[] child, bool createConstraints)
Tạo
DataRelation 
giữa hai bảng bằng cách sử dụng nhiều cột trong mỗi bảng cho liên kết.

DataRelation(string relName, string parentTableName, string childTableName, string[] parentColNames, string[] childColNames, bool isNested)
là một khởi tạo đã sử dụng môi trường Smart Device Extensions.

V i ết mã l ệnh để tạo DataRelation

DataRelation l_newRelation = new DataRelation( "MainContactToCholesterolRelation", 
l_DataSet.Tables["PhoneContactsMainTable"].Columns["ContactID"], 
l_DataSet.Tables["Cholesterol"].Columns["ContactID"]); 
l_DataSet.Relations.Add(l_newRelation);
    
    
0