You are on page 1of 188

TRUNG TÂM TIN HỌC – ĐẠI HỌC KHOA HỌC TỰ NHIÊN TP.

HCM
227 Nguyễn Văn Cừ - Quận 5- Tp.Hồ Chí Minh
Tel: 8351056 – Fax 8324466 – Email: ttth@hcmuns.edu.vn

TAØI LIEÄU HÖÔÙNG DAÃN GIAÛNG DAÏY

CHÖÔNG TRÌNH KYÕ THUAÄT


VIEÂN
NGAØNH LAÄP TRÌNH
Hoïc phaàn 3
VISUAL BASIC .NET

Mã tài liệu: DT_NCM_LT_TLGD_LTN1


Phiên bản 1.2 – Tháng 07/2006
Tài liệu hướng dẫn giảng dạy

MỤC LỤC
GIỚI THIỆU ...........................................................................................................9
GIÁO TRÌNH LÝ THUYẾT......................................................................................10
TÀI LIỆU THAM KHẢO..........................................................................................10

Bài 1.....................................................................................................................11
TỔNG QUAN .NET FRAMEWORK ..........................................................................11

I. Tổng quan về .Net Framework ......................................................................12

II. Cấu trúc .Net Framework...............................................................................14


II.1. Hệ điều hành ...............................................................................................14
II.2. Cung cấp các chức năng xây dựng ứng dụng .................................................14
II.3. Common Language Runtime .........................................................................15
II.4. Bộ thư viện các lớp đối tượng .......................................................................15
II.5. Phân nhóm các lớp đối tượng theo loại ...........................................................16

III. Ứng dụng đầu tiên .........................................................................................17


III.1. Môi trường lập trình VS .NET .........................................................................17
III.2. Tạo mới một project .....................................................................................18
III.3. Ứng dụng Hello ............................................................................................19
III.4. Windows Form Designer................................................................................21
III.5. Thử nghiệm..................................................................................................23
III.6. Kỹ thuật lập trình hướng đối tượng ................................................................25
III.7. Xây dựng lớp đối tượng ................................................................................27
III.8. Sử dụng lại thành phần có sẵn ......................................................................28
III.9. Assembly - một loại DLL mới..........................................................................32

Bài 2.....................................................................................................................34
NGÔN NGỮ VISUAL BASIC .NET ..........................................................................34

I. Các kiểu dữ liệu và đặc điểm .........................................................................35


I.1. Các kiểu dữ liệu ............................................................................................35
I.2. Đặc điểm của các kiểu dữ liệu .......................................................................36

Học phần 3 – VB.NET Trang 2/187


Tài liệu hướng dẫn giảng dạy

II. Biến – Tính chất, khai báo và khởi tạo...........................................................40


II.1. Tính chất .....................................................................................................40
II.2. Khai báo và khởi tạo .....................................................................................41
II.3. Kiểu trị và tham chiếu (Value Type và Reference Type)....................................42
II.4. Kiểu Enum (Enumeration)..............................................................................44

III. Mảng – Structure ...........................................................................................45


III.1. Mảng ...........................................................................................................45
III.2. Structure......................................................................................................47

IV. Các toán tử ....................................................................................................47


IV.1. Toán tử toán học ..........................................................................................47
IV.2. Toán tử nối chuỗi..........................................................................................48
IV.3. Toán tử gán .................................................................................................48
IV.4. Toán tử so sánh............................................................................................48
IV.5. Toán tử luận lý và Bitwise..............................................................................49

V. Cấu trúc điều khiển........................................................................................49


V.1. Cấu trúc chọn ...............................................................................................49
V.2. Cấu trúc lặp..................................................................................................51

VI. Những thay đổi trong VB.NET........................................................................52


VI.1. Thay đổi trong thủ tục và hàm.......................................................................52
VI.2. Khai báo Option Strict ...................................................................................53
VI.3. Kiểu chuỗi có độ dài cố định ..........................................................................54
VI.4. Chỉ thị #Region … #End Region.....................................................................54
VI.5. Imports không gian tên (Namespace).............................................................54

VII. Xử lý lỗi..........................................................................................................55
VII.1. Phân loại lỗi ............................................................................................55
VII.2. Xử lý lỗi ..................................................................................................55

Bài 3.....................................................................................................................59
LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG TRONG VISUAL BASIC .NET ............................59

I. Lập trình hướng đối tượng.............................................................................60


I.1. Tính trừu tượng............................................................................................60
I.2. Tính bao bọc ................................................................................................60

Học phần 3 – VB.NET Trang 3/187


Tài liệu hướng dẫn giảng dạy

I.3. Tính kế thừa.................................................................................................61


I.4. Tính đa hình.................................................................................................61

II. Lập trình hướng đối tượng trong VB.NET ......................................................62


II.1. Tạo một Class...............................................................................................62
II.2. Tạo một NameSpace mới...............................................................................63
II.3. Tạo một Class kế thừa ..................................................................................64
II.4. Khai báo phương thức (Method).....................................................................64
II.5. Khai báo thuộc tính (Property) .......................................................................67
II.6. Khai báo sự kiện (Event) ...............................................................................69
II.7. Từ khóa Me, Mybase, MyClass .......................................................................71
II.8. Khởi tạo thể hiện ..........................................................................................73
II.9. Abstract Base Class .......................................................................................73
II.10. Giao tiếp (Interface)......................................................................................74
II.11. Lớp lồng ghép ..............................................................................................75
II.12. Từ khóa Delegate .........................................................................................76

Bài 4.....................................................................................................................78
TỔNG QUAN VỀ ADO.NET ....................................................................................78

I. Tổng quan......................................................................................................79

II. Kiến trúc ADO .Net.........................................................................................80

III. Các đặc điểm của ADO.Net ............................................................................81


III.1. Interoperability – Tương tác giữa nhiều hệ thống khác nhau ............................81
III.2. Scalability - Hỗ trợ nhiều người dùng..............................................................82
III.3. Productivity - Mở rộng khả năng làm việc với CSDL..........................................82
III.4. Performance - Hiệu quả cao trong xử lý dữ liệu ...............................................82

IV. Content Component.......................................................................................83


IV.1. DataSet........................................................................................................83
IV.2. DataTable ....................................................................................................84
IV.3. DataRelation.................................................................................................84
IV.4. Ràng buộc trên quan hệ ................................................................................84
IV.5. DataView .....................................................................................................85

V. Managed Provider Component ......................................................................85

Học phần 3 – VB.NET Trang 4/187


Tài liệu hướng dẫn giảng dạy

V.1. Connection ..................................................................................................86


V.2. Command ....................................................................................................86
V.3. DataReader .................................................................................................86
V.4. DataAdapter.................................................................................................86

Bài 5.....................................................................................................................88
CONNECTION, COMMAND, DATAADAPTER .........................................................88

I. Connection.....................................................................................................89
I.1. Data Provider ...............................................................................................89
I.2. ConnectionString ..........................................................................................89
I.3. Các thuộc tính khác của Connection ...............................................................91
I.4. Các phương thức trên Connection ..................................................................91
I.5. Minh họa tạo Connection ...............................................................................91

II. Command ......................................................................................................92


II.1. Tạo Command ..............................................................................................92
II.2. Các thuộc tính của Command ........................................................................92
II.3. Parameter ....................................................................................................93
II.4. Thực hiện Command .....................................................................................95
II.5. DataReader ..................................................................................................96

III. DataAdapter ..................................................................................................97


III.1. Tạo DataAdapter ..........................................................................................97
III.2. Các thuộc tính chính của DataAdapter ............................................................98
III.3. Các chức năng của DataAdapter.....................................................................99

Bài 6...................................................................................................................105
DATASET, DATATABLE, DATARELATION VÀ DATAVIEW ....................................105

I. DataSet........................................................................................................106
I.1. Khai báo DataSet ........................................................................................ 106
I.2. Các thuộc tính của DataSet.......................................................................... 106
I.3. Các phương thức của DataSet .................................................................... 106

II. DataTable ....................................................................................................112


II.1. Các thuộc tính của DataTable ...................................................................... 112
II.2. DataColumn ............................................................................................... 113

Học phần 3 – VB.NET Trang 5/187


Tài liệu hướng dẫn giảng dạy

II.3. DataRow .................................................................................................... 115


II.4. Constraint .................................................................................................. 117
II.5. Tập hợp Columns........................................................................................ 119
II.6. Tập hợp Rows ............................................................................................ 121
II.7. Tập hợp Constraints.................................................................................... 124
II.8. Một số phương thức của DataTable .............................................................. 124
II.9. Các sự kiện của DataTable........................................................................... 126

III. DataRelation................................................................................................127
III.1. Khởi tạo ..................................................................................................... 127
III.2. Các thuộc tính của DataRelation................................................................... 128
III.3. Minh họa thiết lập quan hệ .......................................................................... 128

IV. DataView .....................................................................................................129


IV.1. Khởi tạo ..................................................................................................... 129
IV.2. Các thuộc tính chính của DataView............................................................... 129
IV.3. Các thao tác chính của DataView ................................................................. 130
IV.4. DataRowView ............................................................................................. 131

Bài 7...................................................................................................................133
XÂY DỰNG CÁC LỚP XỬ LÝ................................................................................133

I. Mô hình đa tầng (N-tier)..............................................................................134

II. Xây dựng lớp xử lý lưu trữ...........................................................................134


II.1. Các khai báo .............................................................................................. 135
II.2. Khai báo các thuộc tính ............................................................................... 135
II.3. Khai báo phương thức khởi tạo .................................................................... 137
II.4. Khai báo phương thức xử lý - cung cấp thông tin .......................................... 137
II.5. Khai báo các phương thức thực hiện lệnh ..................................................... 139
II.6. Nhóm xử lý sự kiện..................................................................................... 140

III. Xây dựng lớp xử lý nghiệp vụ ......................................................................140


III.1. Khai báo phương thức khởi tạo .................................................................... 140
III.2. Khai báo phương thức tìm kiếm thông tin ..................................................... 141

Bài 8...................................................................................................................142
THIẾT KẾ CÁC MÀN HÌNH ..................................................................................142

Học phần 3 – VB.NET Trang 6/187


Tài liệu hướng dẫn giảng dạy

I. Các điều khiển hiển thị dữ liệu ....................................................................143


I.1. Thuộc tính liên kết dữ liệu của điều khiển ..................................................... 143
I.2. ComboBox, ListBox, CheckListBox ................................................................ 143
I.3. DataGrid .................................................................................................... 144
I.4. DataGridTableStyle và TableStyles................................................................ 146
I.5. DataGridColumnStyle và GridColumnStyles.................................................... 146
I.6. Thiết kế DataGrid........................................................................................ 147
I.7. Hiển thị dữ liệu ra điều khiển ....................................................................... 150

II. Màn hình đơn...............................................................................................152


II.1. Các khai báo .............................................................................................. 152
II.2. Các thủ tục nhập xuất ................................................................................. 152
II.3. Các hàm kiểm tra........................................................................................ 153
II.4. Các xử lý sự kiện ........................................................................................ 154

III. Màn hình một nhiều.....................................................................................157


III.1. Màn hình một-nhiều hai trang ...................................................................... 157
III.2. Màn hình một-nhiều ba trang....................................................................... 159

IV. Màn hình lọc dữ liệu ....................................................................................160


IV.1. Màn hình lọc một điều kiện.......................................................................... 160
IV.2. Màn hình lọc hai điều kiện ........................................................................... 161

V. Màn hình một-nhiều-nhiều ..........................................................................161

VI. Một số kỹ thuật trong hiển thị dữ liệu .........................................................161


VI.1. Tạo lớp DataGridColumnStyle chuyển đổi dữ liệu hiển thị ............................... 161
VI.2. Tạo lớp DataGridColumnStyle có ComboBox.................................................. 162
VI.3. Tạo lớp DataGridColumnStyle cho phép định dạng chi tiết.............................. 162
VI.4. Minh họa sử dụng ....................................................................................... 162

Bài 9...................................................................................................................166
BÁO BIỂU CRYSTAL REPORT .............................................................................166

I. Giới thiệu Crystal Report .............................................................................167

II. Tạo báo biểu ................................................................................................167


II.1. Nguồn dữ liệu cho báo biểu ......................................................................... 169
II.2. Sử dụng Crystal Report Viewer để hiển thị báo biểu....................................... 170

Học phần 3 – VB.NET Trang 7/187


Tài liệu hướng dẫn giảng dạy

II.3. Nguồn dữ liệu cho báo biểu từ DataSet ........................................................ 171


II.4. Định lại dữ liệu cho báo biểu từ nguồn CSDL................................................. 173
II.5. Lọc dữ liệu báo biểu.................................................................................... 175
II.6. Truyền tham số cho báo biểu....................................................................... 175
II.7. Các loại kết xuất báo biểu............................................................................ 175
ĐỀ THI MẪU CUỐI HỌC PHẦN ...........................................................................177
ĐỀ THI MẪU KIỂM TRA CHUYÊN MÔN GIÁO VIÊN ............................................181

Học phần 3 – VB.NET Trang 8/187


Tài liệu hướng dẫn giảng dạy

GIỚI THIỆU
Sau khi hoàn thành khóa học này, học viên sẽ có các khả năng:
ƒ Lập trình hướng đối tượng với Visual Basic .Net
ƒ Lập trình cơ sở dữ liệu với ADO.Net
ƒ Xây dựng ứng dụng với Visual Basic .Net
Với thời lượng là 36 tiết LT và 60 tiết TH được phân bổ như sau:

STT Bài học Số tiết LT Số tiết TH

1 Tổng quan .Net Framework, Visual Studio .Net 3

2 Ngôn ngữ Visual Basic .Net 3 5

3 Lập trình hướng đối tượng với VB.Net 6 10

4 Tổng quan ADO.Net 1 00

5 Đối tượng Connection, Command và DataAdapter 2 5

6 DataSet, DataTable, DataRelation Và DataView 6 5

7 Xây dựng các lớp xử lý 3 10

8 Thiết kế các màn hình 6 15

9 Báo biểu và in ấn 6 10

Tổng số tiết: 36 60

Học phần 3 – VB.NET Trang 9/187


Tài liệu hướng dẫn giảng dạy

GIÁO TRÌNH LÝ THUYẾT


Sử dụng giáo trình “Visual Basic.Net” tập 2 của Nhóm Chuyên môn Lập trình.

TÀI LIỆU THAM KHẢO

Học phần 3 – VB.NET Trang 10/187


Tài liệu hướng dẫn giảng dạy

HƯỚNG DẪN PHẦN LÝ THUYẾT

Bài 1
TỔNG QUAN .NET FRAMEWORK
Tóm tắt
Lý thuyết 3 tiết

Mục tiêu Các mục chính Bài tập

Giới thiệu các khái niệm cơ bản và 1. Tổng quan .Net Framework
cấu trúc của .Net Framework, đồng 2. Cấu trúc .Net Framework
thời thông qua việc trình bày một
3. Ứng dụng đầu tiên
ứng dụng để giới thiệu về Visual
Studio .Net.

Học phần 3 – VB.NET Trang 11/187


Tài liệu hướng dẫn giảng dạy

I. Tổng quan về .Net Framework


Ngày 13/02/2002, Microsoft chính thức giới thiệu bộ công cụ lập trình mới của mình – Visual
Studio.NET. Sau 4 năm không tung ra phiên bản mới cho bộ Visual Studio 98, lần này Microsoft quyết
tâm đặt cược vào thắng lợi của công nghệ mới: Microsoft .NET.

Trong thời đại công nghệ thông tin, dữ liệu trở nên quan trọng đến nỗi người ta mong muốn tất cả mọi
thứ như điện thoại di động, máy tính xách tay, các máy PDA (Personal Digital Assistant) đều phải kết
nối với nhau để chia sẽ dữ liệu và việc sử dụng các phần mềm để quản lý, sử dụng những dữ liệu đó là
"không biên giới". Ứng dụng phải sẵn sàng để sử dụng từ trên máy tính cũng như trên điện thoại di
động 24/24 giờ, ít lỗi, xử lý nhanh và bảo mật chặt chẽ.
Các yêu cầu này làm đau đầu những chuyên gia phát triển ứng dụng khi phần mềm chủ yếu viết cho
hệ thống này không chạy trên một hệ thống khác bởi nhiều lý do như khác biệt về hệ điều hành, khác
biệt về chuẩn giao tiếp dữ liệu, mạng. Thời gian và chi phí càng trở nên quý báu vì bạn không phải là
người duy nhất biết lập trình. Làm sao sử dụng lại những ứng dụng đã viết để mở rộng thêm nhưng
vẫn tương thích với những kỹ thuật mới?
Sun Microsystems đi đầu trong việc cung cấp giải pháp với Java. Java chạy ổn định trên các hệ điều
hành Unix hay Solaris của Sun từ máy chủ tới các thiết bị cầm tay hay thậm chí trên các hệ điều hành
Windows của Microsoft (một ví dụ rõ ràng đó là hầu hết các điện thoại di động thế hệ mới đều có phần
mềm viết bằng Java). Kiến trúc lập trình dựa trên Java bytecode và thi hành trên máy ảo Java (JVM –
Java Virtual Marchine) cho phép các ứng dụng Java chạy trên bất cứ hệ điều hành nào. Mô hình lập
trình thuần hướng đối tượng của Java giúp các lập trình viên tùy ý sử dụng lại và mở rộng các đối
tượng có sẵn. Các nhà cung cấp công cụ lập trình dựa vào đây đểø gắn vào các môi trường phát triển
ứng dụng bằng Java của mình đủ các thư viện lập trình nhằm hỗ trợ các lập trình viên.
Sức mạnh của Java dường như quá lớn đến nỗi Microsoft từng phải chống trả bằng cách loại bỏ Java
Virtual Marchine khỏi các phiên bản hệ điều hành Windows mới của mình như Windows XP. Tuy nhiên,
Microsoft thừa hiểu rằng dù không cung cấp JVM, Sun cũng có thể tự cung cấp các JVM package cho
những người dùng Windows. Đó là lý do tại sao nhà khổng lồ quyết định bắt tay xây dựng lại từ đầu
một nền tảng phát triển ứng dụng mới: Microsoft.NET Framework.
Vì ra đời khá muộn so với Java, .Net bị coi là khá giống với bậc "tiền bối" của nó. .NET sử dụng kỹ
thuật lập trình thuần hướng đối tượng như Java và cũng thi hành trên một máy ảo là CLR (Common
Language Runtime).
Bộ thư viện của .NET Framework bao gồm hơn 5000 lớp đối tượng đủ sức hỗ trợ hầu hết các yêu cầu
từ phía lập trình viên. Công nghệ mã nguồn mở được đưa vào .NET thay cho COM và DCOM đang được
các lập trình viên của Microsoft sử dụng. Với COM, những thành phần (COMponent) đã được xây dựng
như các lớp thư viện hay các control chỉ có thể sử dụng lại. Bạn không thể mở rộng chúng hay viết lại
cho thích hợp với ứng dụng của mình. Trong .NET, mọi thành phần đều có thể kế thừa và mở rộng,
một kỹ thuật mới được đưa ra thay cho COM là Assembly. Distributed Component hay DCOM là kỹ
thuật dùng để phối hợp các thành phần trên nhiều máy tính giờ đây được thay thế trong .NET bởi
chuẩn công nghệ mới là SOAP và XML Web Service.
Cùng với SOAP (Simple Objects Access Protocol), XML Web Service mở rộng khả năng của DCOM từ
chỗ chỉ phối hợp các máy trong Intranet, nằm sau Firewall ra Internet. Các công ty .com giờ đây mặc
sức xây dựng các phần mềm độc lập của mình những vẫn có thể phối hợp với nhau để đem tới khách

Học phần 3 – VB.NET Trang 12/187


Tài liệu hướng dẫn giảng dạy

hàng các dịch vụ e-commerce đa dạng nhưng thống nhất.


XML (eXtended Markup Language) - chuẩn lưu trữ và trao đổi dữ liệu mới nhất, hiệu quả nhất hiện nay
cũng được .NET hỗ trợ khá đầy đủ. Chỉ cần một công cụ chuyển đổi đơn giản mà thậm chí bạn cũng có
thể tự viết (đương nhiên khi bạn đã biết về XML), các dữ liệu trước kia của bạn dù ở bất cứ dạng lưu
trữ nào cũng có thể chuyển về dạng XML để sử dụng trong các ứng dụng mới hay trao đổi với hệ thống
ứng dụng khác. .NET giờ đây cũng sử dụng kỹ thuật truy cập cơ sở dữ liệu mới là ADO.NET để bổ sung
cho kỹ thuật ADO - trước kia vốn là thành phần mạnh nhất trong MDAC (Microsoft Data Access
Component gồm có 3 phần DB-Lib, OLEDB và ADO)- khả năng làm việc với dữ liệu XML. Bạn cũng nên
biết rằng kể từ SQL Server 2000, XML đã được hỗ trợ trong phần mềm quản trị cơ sở dữ liệu nổi tiếng
nhất của Microsoft và phiên bản SQL Server sắp tới chắc chắn không xem nhẹ XML chút nào. Cùng với
XML, SOAP và Web service đang là những vũ khí mạnh nhất mà Microsoft sử dụng để qua mặt Java.
Cũng không thể quên CLR, máy ảo của các ứng dụng viết bằng .NET. Common Language Runtime
(CLR) được sử dụng để thực hiện các đoạn chương trình ở dạng mã IL (Immediate Language). Điều
này có nghĩa là dầu bạn lập trình bằng ngôn ngữ nào bạn thích, một khi có thể biên dịch sang mã IL,
bạn sẽ yên tâm rằng CLR sẽ thi hành nó một cách suôn sẽ. Giống như JVM của Java, CLR bao gồm
trong nó nhiều thành phần quản lý ứng dụng khi thi hành như JIT (Just In Time compiler) để biên dịch
ngay tại thời điểm thi hành những đoạn lệnh IL cần thiết hay Garbage Collector giữ vai trò thu gom
"rác rưởi" mà ứng dụng để sót lại nhằm sử dụng hiệu quả bộ nhớ. Ngoài ra, CLR không quên hỗ trợ
việc quản lý các ứng dụng trước đây viết trên kỹ thuật COM. Nó đảm bảo cho bạn không phải bỏ đi
những gì đã "dày công xây đắp" trước đây mà vẫn có thể phối hợp nó với các ứng dụng mới viết trên
.NET.

Một điểm nữa không thể bỏ qua khi giới thiệu về .NET Framework, đó là thành phần Common
Language Specification. Vai trò của thành phần này là đảm bảo sự tương tác giữa các đối tượng bất
chấp chúng được xây dựng trong ngôn ngữ nào, miễn là chúng cung cấp được những thành phần
chung của các ngôn ngữ muốn tương tác. Thành phần Common Language Runtime được xây dựng với
mục đích mô tả các yêu cầu cần thiết của một ngôn ngữ để có thể sử dụng trong lập trình và biên dịch
thành mã IL. Một khi đã ở dạng mã IL, ứng dụng đã có thể chạy trên CLR và như thế bạn đã có khả
năng dùng ngôn ngữ lập trình mà mình yêu thích để tận dụng các khả năng mạnh mẽ của .NET.

Trước đây, các lập trình viên đã quen dùng Visual C++ hay Visual Basic 6 hay Visual InterDEV mỗi khi
cần xây dựng một loại ứng dụng khác phải chuyển qua lại giữa các môi trường lập trình khác nhau của
Visual Studio 98 và chợt nhận ra rằng VB 6 không có điểm mạnh này của C++ hoặc C++ không làm
nhanh được chức năng kia của VB 6,… sẽ cảm thấy nhẹ nhõm vì với .NET giờ đây, mọi sức mạnh của
các ngôn ngữ lập trình đều như nhau. .NET Framework hỗ trợ một bộ thư viện lập trình đồ sộ hơn
5000 lớp đối tượng để bạn đủ khả năng xây dựng các loại ứng dụng từ kiểu console (ứng dụng dòng
lệnh), ứng dụng trên Windows cho tới các ứng dụng Web, các service của hệ điều hành và các Web
service trên Internet.

Trước khi chấm dứt phần giới giới thiệu, cũng cần phải đề cập đến bộ control đồ sộ và mới mẻ của
.NET. Rất nhiều điều khiển mới được thêm vào .NET Framework để hỗ trợ cho các ứng dụng có giao
diện đồ họa trên Windows và trên Web một "vẻ mặt" mới. Những công cụ này không chỉ hỗ trợ chuẩn
font chữ Unicode nhưng còn kết hợp với khả năng xây dựng ứng dụng mang tính "quốc tế" khi người
lập trình phải đáp ứng nhiều ngôn ngữ, nhiều định dạng ngày giờ hay tiền tệ khác nhau.
Microsoft không quên đem lại một môi trường phát triển ứng dụng sử dụng giao diện đồ hoạ, tích hợp
nhiều chức năng, tiện ích khác nhau để hỗ trợ tối đa cho các lập trình viên, đó chính là Visual

Học phần 3 – VB.NET Trang 13/187


Tài liệu hướng dẫn giảng dạy

Studio.NET.
.NET Framework là thành phần quan trọng nhất trong kỹ thuật phát triển ứng dụng dựa trên .NET.
Visual Studio sẽ giúp người lập trình nắm bắt và tận dụng tốt hơn những chức năng của .NET
Framework. Phần dưới đây giới thiệu những kiến thức cơ bản nhất về .NET Framework trước khi chúng
ta thực sự bắt tay vào làm việc với Visual Studio.NET và VB.NET.

II. Cấu trúc .Net Framework


Trong phần này, chúng ta tìm hiểu các thành phần bên trong .NET Framework.

VB C ++ C# J# …

Common Language Specification

ASP .NET Windows


Web Forms Web Services Forms
Mobile Internet Toolkit

ADO .NET and XML

B a s e C la s s L ib ra ry

Common Language Runtime

Operating System

Cấu trúc .NET FrameworkN

II.1. Hệ điều hành


.NET Framework cần được cài đặt và sử dụng trên một hệ điều hành. Hiện tại, .NET Framework chỉ có
khả năng làm việc trên các hệ điều hành Microsoft Win32 và Win64 mà thôi. Trong thời gian tới,
Microsoft sẽ đưa hệ thống này lên Windows CE cho các thiết bị cầm tay và có thể mở rộng cho các hệ
điều hành khác như Unix.

II.2. Cung cấp các chức năng xây dựng ứng dụng
Với vai trò quản lý việc xây dựng và thi hành ứng dụng, .NET Framework cung cấp các lớp đối tượng
(Class) để bạn có thể gọi thi hành các chức năng mà đối tượng đó cung cấp. Tuy nhiên, lời kêu gọi của
bạn có được "hưởng ứng" hay không còn tùy thuộc vào khả năng của hệ điều hành đang chạy ứng
dụng của bạn.
Các chức năng đơn giản như hiển thị một hộp thông báo (Messagebox) sẽ được .NET Framework sử
dụng các hàm API của Windows. Chức năng phức tạp hơn như sử dụng các COMponent sẽ yêu cầu
Windows phải cài đặt Microsoft Transaction Server (MTS) hay các chức năng trên Web cần Windows
phải cài đặt Internet Information Server (IIS).
Như vậy, bạn cần biết rằng lựa chọn một hệ điều hành để cài đặt và sử dụng .NET Framework cũng
không kém phần quan trọng. Cài đặt .NET Framework trên các hệ điều hành Windows 2000, 2000

Học phần 3 – VB.NET Trang 14/187


Tài liệu hướng dẫn giảng dạy

Server, XP, XP.NET, 2003 Server sẽ đơn giản và tiện dụng hơn trong khi lập trình.

II.3. Common Language Runtime


Là thành phần "kết nối" giữa các phần khác trong .NET Framework với hệ điều hành. Common
Language Runtime (CLR) giữ vai trò quản lý việc thi hành các ứng dụng viết bằng .NET trên Windows.
CLR sẽ thông dịch các lời gọi từ chương trình cho Windows thi hành, đảm bảo ứng dụng không chiếm
dụng và sử dụng tràn lan tài nguyên của hệ thống. Nó cũng không cho phép các lệnh "nguy hiểm"
được thi hành. Các chức năng này được thực thi bởi các thành phần bên trong CLR như Class loader,
Just In Time compiler, Garbage collector, Exception handler, COM marshaller, Security engine,…
Trong các phiên bản hệ điều hành Windows mới như XP.NET và Windows 2003, CLR được gắn kèm với
hệ điều hành. Điều này đảm bảo ứng dụng viết ra trên máy tính của chúng ta sẽ chạy trên máy tính
khác mà không cần cài đặt, các bước thực hiện chỉ đơn giản là một lệnh copy của DOS!

II.4. Bộ thư viện các lớp đối tượng


Nếu phải giải nghĩa từ "Framework" trong thuật ngữ .NET Framework thì đây là lúc thích hợp nhất.
Framework chính là một tập hợp hay thư viện các lớp đối tượng hỗ trợ người lập trình khi xây dựng
ứng dụng. Có thể một số người trong chúng ta đã nghe qua về MFC và JFC. Microsoft Foundation Class
là bộ thư viện mà lập trình viên Visual C++ sử dụng trong khi Java Foundation Class là bộ thư viện
dành cho các lập trình viên Java. Giờ đây, có thể coi .NET Framework là bộ thư viện dành cho các lập
trình viên .NET

Với hơn 5000 lớp đối tượng để gọi thực hiện đủ các loại dịch vụ từ hệ điều hành, chúng ta có thể bắt
đầu xây dựng ứng dụng bằng Notepad.exe!!!… Nhiều người lầm tưởng rằng các môi trường phát triển
phần mềm như Visual Studio 98 hay Visual Studio.NET là tất cả những gì cần để viết chương trình.
Thực ra, chúng là những phần mềm dùng làm "vỏ bọc" bên ngoài. Với chúng, chúng ta sẽ viết được
các đoạn lệnh đủ các màu xanh, đỏ; lỗi cú pháp báo ngay khi đang gõ lệnh; thuộc tính của các đối
tượng được đặt ngay trên cửa sổ properties, giao diện được thiết kế theo phong cách trực quan… Như
vậy, chúng ta có thể hình dung được tầm quan trọng của .NET Framework. Nếu không có cái cốt lõi
.NET Framework, Visual Studio.NET cũng chỉ là cái vỏ bọc! Nhưng nếu không có Visual Studio.NET,
công việc của lập trình viên .NET cũng lắm bước gian nan!

II.4.1. Base class library – thư viện các lớp cơ sở


Đây là thư viện các lớp cơ bản nhất, được dùng trong khi lập trình hay bản thân những người xây dựng
.NET Framework cũng phải dùng nó để xây dựng các lớp cao hơn. Ví dụ các lớp trong thư viện này là
String, Integer, Exception,…

II.4.2. ADO.NET và XML


Bộ thư viện này gồm các lớp dùng để xử lý dữ liệu. ADO.NET thay thế ADO để trong việc thao tác với
các dữ liệu thông thường. Các lớp đối tượng XML được cung cấp để bạn xử lý các dữ liệu theo định
dạng mới: XML. Các ví dụ cho bộ thư viện này là SqlDataAdapter, SqlCommand, DataSet, XMLReader,
XMLWriter,…

II.4.3. ASP.NET
Bộ thư viện các lớp đối tượng dùng trong việc xây dựng các ứng dụng Web. ASP.NET không phải là
phiên bản mới của ASP 3.0. Ứng dụng web xây dựng bằng ASP.NET tận dụng được toàn bộ khả năng

Học phần 3 – VB.NET Trang 15/187


Tài liệu hướng dẫn giảng dạy

của .NET Framework. Bên cạnh đó là một "phong cách" lập trình mới mà Microsoft đặt cho nó một tên
gọi rất kêu : code behind. Đây là cách mà lập trình viên xây dựng các ứng dụng Windows based
thường sử dụng – giao diện và lệnh được tách riêng. Tuy nhiên, nếu bạn đã từng quen với việc lập
trình ứng dụng web, đây đúng là một sự "đổi đời" vì bạn đã được giải phóng khỏi mớ lệnh HTML lộn
xộn tới hoa cả mắt.
Sự xuất hiện của ASP.NET làm cân xứng giữa quá trình xây dựng ứng dụng trên Windows và Web.
ASP.NET cung cấp một bộ các Server Control để lập trình viên bắt sự kiện và xử lý dữ liệu của ứng
dụng như đang làm việc với ứng dụng Windows. Nó cũng cho phép chúng ta chuyển một ứng dụng
trước đây viết chỉ để chạy trên Windows thành một ứng dụng Web khá dễ dàng. Ví dụ cho các lớp
trong thư viện này là WebControl, HTMLControl, …

II.4.4. Web services


Web services có thể hiểu khá sát nghĩa là các dịch vụ được cung cấp qua Web (hay Internet). Dịch vụ
được coi là Web service không nhằm vào người dùng mà nhằm vào người xây dựng phần mềm. Web
service có thể dùng để cung cấp các dữ liệu hay một chức năng tính toán.

Ví dụ, công ty du lịch của bạn đang sử dụng một hệ thống phần mềm để ghi nhận thông tin về khách
du lịch đăng ký đi các tour. Để thực hiện việc đặt phòng khách sạn tại địa điểm du lịch, công ty cần
biết thông tin về phòng trống tại các khách sạn. Khách sạn có thể cung cấp một Web service để cho
biết thông tin về các phòng trống tại một thời điểm. Dựa vào đó, phần mềm của bạn sẽ biết rằng liệu
có đủ chỗ để đặt phòng cho khách du lịch không? Nếu đủ, phần mềm lại có thể dùng một Web service
khác cung cấp chức năng đặt phòng để thuê khách sạn. Điểm lợi của Web service ở đây là bạn không
cần một người làm việc liên lạc với khách sạn để hỏi thông tin phòng, sau đó, với đủ các thông tin về
nhiều loại phòng người đó sẽ xác định loại phòng nào cần đặt, số lượng đặt bao nhiêu, đủ hay không
đủ rồi lại liên lạc lại với khách sạn để đặt phòng. Đừng quên là khách sạn lúc này cũng cần có người để
làm việc với nhân viên của bạn và chưa chắc họ có thể liên lạc thành công.
Web service được cung cấp dựa vào ASP.NET và sự hỗ trợ từ phía hệ điều hành của Internet
Information Server.

II.4.5. Window form


Bộ thư viện về Window form gồm các lớp đối tượng dành cho việc xây dựng các ứng dụng Windows
based. Việc xây dựng ứng dụng loại này vẫn được hỗ trợ tốt từ trước tới nay bởi các công cụ và ngôn
ngữ lập trình của Microsoft. Giờ đây, ứng dụng chỉ chạy trên Windows sẽ có thể làm việc với ứng dụng
Web dựa vào Web service. Ví dụ về các lớp trong thư viện này là: Form, UserControl,…

II.5. Phân nhóm các lớp đối tượng theo loại


Một khái niệm không được thể hiện trong hình vẽ trên nhưng cần đề cập đến là Namespace. Đây là tên
gọi một nhóm các lớp đối tượng phục vụ cho một mục đích nào đó. Chẳng hạn, các lớp đối tượng xử lý
dữ liệu sẽ đặt trong một namespace tên là Data. Các lớp đối tượng dành cho việc vẽ hay hiển thị chữ
đặt trong namespace tên là Drawing.
Một namespace có thể là con của một namespace lớn hơn. Namespace lớn nhất trong .NET Framework
là System.
Lợi điểm của Namespace là phân nhóm các lớp đối tượng, giúp người dùng dễ nhận biết và sử dụng.
Ngoài ra, Namespace tránh việc các lớp đối tượng có tên trùng với nhau không sử dụng được. .NET
Framework cho phép chúng ta tạo ra các lớp đối tượng và các Namespace của riêng mình. Với hơn

Học phần 3 – VB.NET Trang 16/187


Tài liệu hướng dẫn giảng dạy

5000 tên có sẵn, việc đặt trùng tên lớp của mình với một lớp đối tượng đã có là điều khó tránh khỏi.
Namespace cho phép việc này xảy ra bằng cách sử dụng một tên đầy đủ để nói đến một lớp đối tượng.
Ví dụ, nếu muốn dùng lớp WebControls, chúng ta có thể dùng tên tắt của nó là WebControls hay tên
đầy đủ là System.Web.UI.WebControls.
System.Web System.Windows.Forms
Services UI Design
Description HtmlControls
Discovery WebControls
Protocols System.Drawing
Caching Security Drawing2D Printing
Configuration SessionState Imaging Text

System.Data System.Xml
OleDb SqlClient XSLT Serialization
Common SQLTypes XPath

System
Collections IO Security Runtime
Configuration Net ServiceProces InteropServices
Diagnostics Reflection Text Remoting

Globalization Resources Threading Serialization

Hệ thống không gian tên (Namespace)

Đặc điểm của bộ thư viện các đối tượng .NET Framework là sự trải rộng để hỗ trợ tất cả các ngôn ngữ
lập trình .NET như chúng ta thấy ở hình vẽ trên. Điều này sẽ giúp những người mới bắt đầu ít bận tâm
hơn trong việc lựa chọn ngôn ngữ lập trình cho mình vì tất cả các ngôn ngữ đều mạnh ngang nhau.
Cũng bằng cách sử dụng các lớp đối tượng để xây dựng ứng dụng, .NET Framework buộc người lập
trình phải sử dụng kỹ thuật lập trình hướng đối tượng (sẽ được nói tới trong các chương sau).

III. Ứng dụng đầu tiên


III.1. Môi trường lập trình VS .NET
Chúng ta sẽ bắt đầu bằng việc làm quen với môi trường phát triển ứng dụng (IDE) của Visual
Studio.NET. VS.NET có nhiều thay đổi so với VS 98.
Hình dưới là màn hình khởi đầu của VS.NET 2003. Vùng làm việc chính giữa đang hiển thị trang "Start
page" với 3 mục chính: Projects, Online Resource và My Profile.
My Profile ghi nhớ thông tin về người sử dụng VS.NET. Các thông tin chủ yếu liên quan đến cách chúng
ta sẽ sử dụng VS.NET như thế nào. Chẳng hạn như cách hiển thị các cửa sổ, các phím tắt, cách VS.NET
hiển thị màn hình giúp đỡ,…
Online Resource cần một kết nối với Internet để download các thông tin từ website của Microsoft về
máy tính của chúng ta.
Projects liệt kê các project mà chúng ta đã làm việc trong thời gian gần đây. Trên mục này, chúng ta
cũng có thể tạo mới một project bằng cách nhấn vào nút New Project.
Các cửa sổ phụ nhìn thấy trên màn hình gồm có:

Học phần 3 – VB.NET Trang 17/187


Tài liệu hướng dẫn giảng dạy

Màn hình khởi đầu của VS.NET 2003 với Tab My Profile hiện hành
Solution Explorer quản lý một hay nhiều project được nhóm với nhau để tạo thành một solution (giải
pháp hay một hệ thống ứng dụng hoàn chỉnh). Nếu chuyển qua tab Class (Clas…), cửa sổ này liệt kê
các lớp đối tượng trong ứng dụng đang làm việc. Tab Content (Cont…) sẽ hiện thị mục lục của phần
giúp đỡ của VS.NET.
Dynamic help là cửa sổ giúp đỡ thông minh mới có trong VS.NET. Trong khi lập trình, chúng ta chỉ cần
đưa chuột tới một từ khoá như Class, For,… Dynamic help sẽ tự động tìm ra những mục giúp đỡ liên
quan đế từ khoá đó. Nếu chúng ta đang mở một project, phần cửa sổ dành cho Dynamic help còn
dùng để hiển thị cửa số Property giống như của VB 6.
Toolbox liệt kê các control dành cho việc thiết kế giao diện. Một tiện lợi của VS.NET cho các màn hình
độ phân giải thấp là chúng ta có thể thu gọn các cửa sổ kiểu như Solution Explorer và Dynamic help
thành tab nằm dọc theo màn hình như cửa sổ Toolbox chúng ta thấy trong hình. Nếu có nhiều tab,
biểu tượng của tab đó sẽ được hiển thị. Trong hình vẽ một tab khác có tên là Server Explorer được
hiển thị với biểu tượng 2 chiếc máy tính phía trên tab Toolbox.

III.2. Tạo mới một project


Có 2 cách tạo mới một project: chọn menu File | New | Project hay nhấn nút New Project trên tab
Projects của trang khởi động. Hình dưới minh họa cửa sổ New Project hiện ra khi bạn chọn chức năng
tạo mới.
Mục Project Type liệt kê tất cả các loại project có thể tạo bằng VS.NET. Máy tính của chúng tôi chỉ cài
một ngôn ngữ VB.NET thay vì 4 ngôn ngữ là VB.NET, C#, C++ và J# nên hình dưới chỉ cho thấy loại
Visual Basic Project mà không thấy có C# project hay C++ project…
Chỉ riêng với loại VB.Net project, chúng ta đã thấy mục Templates liệt kê rất nhiều kiểu ứng dụng khác
nhau. Một template là một mẫu ứng dụng cụ thể mà VS.NET sẽ phát sinh trước một số đoạn lệnh nhất

Học phần 3 – VB.NET Trang 18/187


Tài liệu hướng dẫn giảng dạy

định. Ví dụ, loại template Windows Application sẽ được VS.NET tạo sẵn một form và phát sinh lệnh cần
thiết để chúng ta có thể chạy ứng dụng ngay sau khi vừa tạo mới!
Hãy bắt đầu bằng ứng dụng phổ biến nhất : Windows Application.
Đặt lại tên cho project trong phần Name là “Hello” và định lại đường dẫn cho thư mục lưu trữ ứng
dụng trong phần Location (tuỳ ý và nếu cần thiết). Cuối cùng, nhấn OK để VS.NET phát sinh project
mới

Cửa sổ tạo một project

III.3. Ứng dụng Hello

Môi trường phát triển ứng dụng VS.Net

Học phần 3 – VB.NET Trang 19/187


Tài liệu hướng dẫn giảng dạy

Trong ứng dụng này, chúng ta sẽ thực hiện các chức năng sau:
– Thiết kế giao diện để làm quen với control mới và thuộc tính mới của các control
– Thiết kế hệ thống thực đơn (menu)
– Tìm hiểu cấu trúc của một ứng dụng Windows Application về mặt mã lệnh
– Viết lệnh và làm quen với giao diện mới của cửa sổ code editor
– Biên dịch, chạy thử ứng dụng
– Tìm hiểu danh sách các file của project
Trước hết, nhấn đúp trên form để xem cửa sổ code editor với các đoạn lệnh của form Form1.

Cửa sổ viết lệnh của Form (Code editor)


Chúng ta sẽ thấy các dòng lệnh nằm trong một mục được khai báo là Class Form1. Class là một lớp đối
tượng và điều này cho thấy ngay bản chất lập trình hướng đối tượng (HĐT) của .NET. Tiếp theo dòng
khai báo là đoạn lệnh:
Ví dụ:

Inherits System.Windows.Forms.Form

Inherits có nghĩa là "kế thừa". Trong lập trình HĐT, điều này có nghĩa là Class được khai báo có đặc
điểm giống hoàn toàn với class mà nó thừa kế. Ở đây, class mà Form1 thừa kế là
System.Windows.Forms.Form. Như vậy, Form1 sẽ có đặc điểm chung giống với bất kỳ form nào trong
các ứng dụng Windows: Một vùng hình chữ nhật, có thanh tiêu đề, các hộp Maximize, Minimize, X; có
thể thay đổi kích thước,…
Tạm bỏ qua phần Windows Form designer generated code để xem phần thủ tục Form1_Load:

Ví dụ: Thủ tục Form1_Load

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _


System.EventArgs) Handles MyBase.Load
End Sub

Như đã từng quen với VB 6, chúng ta biết rằng đây chính là thủ tục bẫy sự kiện Load của form xảy ra
khi chương trình vừa được thi hành. Hãy chú ý đoạn Handles MyBase.Load ở cuối phần khai báo. Với
mỗi thủ tục xử lý sự kiện, giờ đây, VB.NET dùng từ khoá Handles để mô tả sự kiện sẽ xử lý. Viết đoạn
lệnh sau đây để hiển thị một hộp thông báo trong thủ tục Form1_Load:

MsgBox("Form load!!!")

Nhấn F5 để chạy thử chương trình, một hộp thông báo hiển thị câu "Form load!!!" trước khi form được
hiện ra. Bây giờ, chúng ta hãy bỏ phần Handles MyBase.Load và chạy lại : hộp thông báo không còn
hiện ra được nữa – nghĩa là không có dòng lệnh nào cho xử lý sự kiện Load của form.

Học phần 3 – VB.NET Trang 20/187


Tài liệu hướng dẫn giảng dạy

III.4. Windows Form Designer


Trên VB 6, các chi tiết thiết kế giao diện trên một form sẽ được dấu đi trong cửa sổ lệnh mặc dù vẫn
được ghi vào tập tin .frm. Trên VB.NET, mọi chi tiết thiết kế giao diện đều sử dụng lệnh. Windows
Form Designer cho phép chúng ta thiết kế giao diện bình thường và sẽ tự phát sinh những đoạn lệnh
này.
Hãy thiết kế form để có giao diện như sau:

Một chú ý nhỏ là Label control không còn sử


dụng thuộc tính Caption nữa và cả đối tượng
form cũng vậy. Các đối tượng control trên
.NET đều thống nhất sử dụng thuộc tính Text
để hiển thị chuỗi ký tự. Bây giờ, chúng ta hãy
quay trở lại cửa sổ Code editor và nhấn chuột
vào dấu + trong phần Windows Form
Giao diện form cần thiết kế Designer.
Chức năng mới của Code editor là thu hẹp các đoạn lệnh thành một dòng ghi chú để toàn bộ phần mã
lệnh trở nên ngắn hơn. Để làm việc này, bạn sử dụng từ khoá #Region "ghi chú…" và #End Region.
Các đoạn lệnh nằm giữa #Region và #End Region sẽ được thu lại chỉ còn một dòng với nội dung là
phần ghi chú và dấu + ở phía trước. Windows Form Designer đã sử dụng chức năng này để phát sinh
đoạn lệnh thiết kế giao diện cho form.

Học phần 3 – VB.NET Trang 21/187


Tài liệu hướng dẫn giảng dạy

Chúng ta sẽ đi vào xem xét chi tiết đoạn lệnh được phát sinh trên đây để hiểu rõ thêm một vài điểm
trong lập trình hướng đối tượng.
Trong lập trình HĐT, mỗi một đối tượng (object) đều phải có một lớp đối tượng (class) định nghĩa nó.
Lớp đối tượng chỉ là một khái niệm chẳng hạn như Máy tính, còn đối tượng là một cái máy tính cụ thể
chúng ta đang dùng. Một lớp được định nghĩa trong VB.NET bằng từ khoá Class như trong chương
trình, chúng ta có một lớp là Form1. Từ đây, chúng ta dùng từ class thay cho cụm từ "lớp đối tượng"
để ngắn gọn hơn.
Một class cần định nghĩa cách đối tượng của nó được tạo ra và huỷ đi. Điều này giống như việc Toyota
tạo ra một model xe hơi mới có tên là VIOS sẽ định nghĩa quy trình sản xuất ra một chiếc VIOS cụ thể
như thế nào. Thủ tục mô tả cách tạo ra một đối tượng của class phải đặt tên là New. Trong đoạn lệnh,
bạn thấy class Form1 cũng có một thủ tục New. Thủ tục định nghĩa cách huỷ đi một đối tượng gọi là
Dispose.
Sau khi các chiếc xe VIOS được đưa vào sử dụng, Toyota nhận được phản hồi từ khách hàng và quyết
định đưa ra một phiên bản VIOS mới hơn là VIOS Pro. VIOS Pro chính là một model mới dựa trên
model VIOS trước đó với một số chức năng cải tiến và vài thiết bị gắn thêm. Trong lập trình HĐT, ta
gọi đây là sự kế thừa. Trở lại phần khai báo Class Form1, bạn sẽ thấy phần Inherits
System.Windows.Forms.Form. Điều này có nghĩa là class Form1 kế thừa đặc điểm của class Form. Dĩ
nhiên các kỹ sư của Toyota sẽ không bỏ thời gian định nghĩa lại cách tạo ra một chiếc VIOS Pro, thay
vào đó họ sẽ mô tả rằng "một chiếc VIOS Pro được tạo ra giống như một chiếc VIOS cộng thêm một số
thay đổi …" Lập trình HĐT cũng dùng cách này, chúng ta thấy trong Sub New() có đoạn lệnh
MyBase.New(). Từ khoá MyBase dùng để nói đến lớp cha của Form1 tức Form. Như thế, Form1 sẽ
được tạo ra giống như một Form bình thường cộng với một vài thay đổi. Những thay đổi này được liệt
kê trong phần InitializeComponent().
Form1 là một Form bình thường mà chúng ta đã gắn thêm một label và một textbox. Thủ tục
InitializeComponent() mô tả cách chúng ta gắn thêm label và textbox đó.

Ví dụ: Nội dung thủ tục InitializeComponent()


Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents txtTen As System.Windows.Forms.TextBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Label1 = New System.Windows.Forms.Label
Me.txtTen = New System.Windows.Forms.TextBox
Me.SuspendLayout()

'Label1
Me.Label1.AutoSize = True
Me.Label1.Location = New System.Drawing.Point(16, 32)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(67,16)
Me.Label1.TabIndex = 0
Me.Label1.Text = "Tên của bạn"

Học phần 3 – VB.NET Trang 22/187


Tài liệu hướng dẫn giảng dạy

'txtTen
Me.txtTen.Location = New System.Drawing.Point(88,24)
Me.txtTen.Name = "txtTen"
Me.txtTen.TabIndex = 1
Me.txtTen.Text = ""

'Form1
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(296,69)
Me.Controls.Add(Me.txtTen)
Me.Controls.Add(Me.Label1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub

Windows Form Designer khai báo hai biến Label1 và txtTen bằng từ khoá Friend (Các từ khoá Public,
Private, Friend,… sẽ được chúng tôi trình bày trong chương 3.) Biến Label1 được khai báo là một đối
tượng của class Label trong khi txtTen là đối tượng của class TextBox. Khai báo một đối tượng không
có nghĩa là chúng ta đã có thể sử dụng đối tượng. Điều này giống như việc đặt hãng Toyota một chiếc
VIOS và phải đợi họ giao hàng trước khi sử dụng. Trong lập trình HĐT, biến kiểu đối tượng sau khi khai
báo cần được "tạo mới". Đây là lý do có hai dòng lệnh:

Me.Label1 = New System.Windows.Forms.Label


Me.txtTen = New System.Windows.Forms.TextBox

Từ khoá Me cũng như các đoạn lệnh còn lại không xa lạ với chúng ta. Ở đây, Designer đang khởi gán
các thuộc tính cho Label1 và txtTen. Một chú ý nhỏ là để đặt vị trí của Label hay TextBox trên Form1,
designer sử dụng một điểm để canh góc trên bên trái. Điểm cũng là một đối tượng của class Point và
được tạo ra bằng lệnh New System.Drawing.Point(x,y).

Hai dòng lệnh Controls.Add(…) làm công việc "bắt vít" hai điều khiển của chúng ta vào Form1.

III.5. Thử nghiệm


Chúng ta sẽ kiểm chứng lại những gì vừa phân tích ở trên bằng việc thêm một control mới vào Form1
nhưng dùng lệnh thay vì thiết kế bằng tay. Thêm dòng khai báo sau dưới mục khai báo txtTen:

Friend WithEvents LinkLbl As System.Windows.Forms.LinkLabel

Và tạo mới:

Me.LinkLbl = New System.Windows.Forms.LinkLabel

Trước mục ghi chú ‘Form1, thêm đoạn lệnh để đặt thuộc tính cho LinkLabel:

Ví dụ: Thủ tục Form1_Load

'LinkLbl
Me.LinkLbl.Location = New System.Drawing.Point(112, 48)

Học phần 3 – VB.NET Trang 23/187


Tài liệu hướng dẫn giảng dạy

Me.LinkLbl.Name = "LinkLbl"
Me.LinkLbl.Size = New System.Drawing.Size(64, 16)
Me.LinkLbl.TabIndex = 2
Me.LinkLbl.TabStop = True
Me.LinkLbl.Text = "Giúp đỡ"
Me.LinkLbl.TextAlign = System.Drawing.ContentAlignment.MiddleCenter

Cuối cùng, chúng ta cũng "bắt vít" LinkLabel vừa tạo vào Form1 bằng lệnh:

Me.Controls.Add(Me.LinkLbl)

Thêm các điều khiển vào form


Bây giờ, chuyển sang cửa sổ thiết kế giao diện để xem LinkLabel của chúng ta được đặt ở đâu. Tiếp tục
thiết kế giao diện cho Form1 theo hình dưới đây:

Thực đơn của form


Menu của form là một điều khiển có tên là MainMenu. Khi được đưa vào form, điều khiển này sẽ nằm
trong phần đáy màn hình như trên hình trên. Mục Type Here hiện ra tại vị trí của menu để chúng ta
thiết kế các mục trong menu. Hãy xem hình để biết cấu trúc của menu cần thiết kế.
Thêm các đoạn lệnh xử lý sự kiện sau vào chương trình:
Ví dụ:
Private Sub cmdHello_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles cmdHello.Click
Dim ten As String
ten = txtTen.Text
MsgBox("Hello, " & ten)
End Sub

Private Sub mnuGioiThieu_Click(ByVal sender As System.Object, ByVal e _

Học phần 3 – VB.NET Trang 24/187


Tài liệu hướng dẫn giảng dạy

As System.EventArgs) Handles mnuGioiThieu.Click


MsgBox("Chương trình VB.NET đầu tiên.")
End Sub

Private Sub mnuThoat_Click(ByVal sender As System.Object, ByVal e As _


System.EventArgs) Handles mnuThoat.Click
Me.Close()
End Sub

Private Sub LinkLbl_LinkClicked(ByVal sender As System.Object, ByVal e _


As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles _
LinkLbl.LinkClicked
Dim P As System.Diagnostics.Process
P.Start("http://ncmlt.hcmuns.edu.vn")
End Sub

Private Sub mnuGiupDo_Click(ByVal sender As System.Object, ByVal e As _


System.EventArgs) Handles mnuGiupDo.Click
Dim P As System.Diagnostics.Process
P.Start("http://ncmlt.hcmuns.edu.vn")
End Sub

Bây giờ, chúng ta có thể biên dịch và chạy thử chương trình bằng cách nhấn phím F5. Các chức năng
khá đơn giản, ngoài việc chúng ta đã dùng một điều khiển LinkLabel mới có trong .NET để mở website
http://ncmlt.hcmuns.edu.vn trong Internet Explorer. Trong đoạn lệnh dành cho chức năng này, chúng
ta dùng một đối tượng P của class Process. Đây là một đối tượng "hệ thống" chưa từng có trong VB 6.
Đối tượng này có thể khởi động hay tắt các ứng dụng có trên máy một cách đơn giản như chúng ta
được thấy.

III.6. Kỹ thuật lập trình hướng đối tượng


Chúng ta sẽ tìm hiểu thêm về cấu trúc của chương trình Hello để nắm vững cách VS.NET tổ chức một
project và hiểu thêm về kỹ thuật lập trình HĐT. Hãy xem hình cửa ổ Solution Explorer bên dưới. Chúng
ta đang ở tab Solution (Soluti…) và VS.NET trình bày cấu trúc của project dạng cây:

Học phần 3 – VB.NET Trang 25/187


Tài liệu hướng dẫn giảng dạy

Cửa sổ Solution Explorer hiển thị các tham chiếu


Form1.vb là đối tượng đại diện cho Form1 trong chương trình. Đây cũng là một file cùng tên lưu trong
thư mục của project Hello.

Reference là một mục liệt kê tất cả các lớp thư viện mà chương trình của chúng ta đang "tham khảo".
Mỗi mục trong Reference là một namespace hay một thư viện nhiều class. Trong chương trình, chúng
ta chỉ có quyền khai báo biến đối tượng là một đối tượng của các class có trong namespace đã liệt kê
trong phần References.

Cửa sổ Class View


Có một số namespace chúng ta không sử dụng tới nhưng mặc định được VS.Net tham khảo tới khi tạo
project mới. Đó là System.XML. Mặc dù đây là namespace rất cơ bản nhưng vì không dùng tới trong
Hello, chúng ta có thể bỏ đi. Nhắp chuột phải trên namespace và chọn mục Remove để xoá. Bây giờ có
thể nhấn F5 và chương trình vẫn chạy bình thường!

Học phần 3 – VB.NET Trang 26/187


Tài liệu hướng dẫn giảng dạy

Kỹ thuật lập trình HĐT bao gồm hai điểm quan trọng: Xây dựng các lớp đối tượng (Component) và sử
dụng lại những đối tượng có sẵn. Một ứng dụng đơn giản có thể chỉ cần ghép nối những đối tượng có
sẵn mà thành như trong ứng dụng Hello. Reference chính là nơi khai báo những thành phần cần thiết
để ghép nối thành một ứng dụng và chúng ta không cần phải khai báo những thành phần thừa như
System.XML.
Với những ứng dụng phức tạp hơn, chúng ta sẽ cần tự mình tạo ra những đối tượng mới. Trong ví dụ
này, chúng ta sẽ tạo ra lớp đối tượng có tên là SayHi để nói lời chào tuỳ theo buổi sáng, trưa hay tối.
Trước hết, hãy chuyển qua tab Class trên cửa sổ Solution Explorer để xem cấu trúc của class Form1
(hình trên)

III.7. Xây dựng lớp đối tượng


Bây giờ, chúng ta sẽ bắt tay vào xây dựng lớp đối tượng đầu tiên: SayHi.
Chọn menu Projects | Add Class… Cửa sổ Add new item sẽ hiện ra với đối tượng được thêm mới vào là
một Class. Bạn gõ vào phần Name chuỗi SayHi.vb và VS.NET sẽ tạo ra một class có tên là SayHi.
Nội dung của SayHi hiện giờ chỉ là một khung khai báo lớp đối tượng:

Class vừa tạo xuất hiện trên Solution Explorer


Nếu bạn xem trên cửa sổ Solution Explorer thì lúc này sẽ thấy có hai class như hình trên bên trái. Bạn
hãy viết đoạn lệnh sau cho class SayHi:

Ví dụ:
Public Class SayHi
Dim mTen As String

Sub New(ByVal Ten As String)


mTen = Ten
End Sub

Property Ten() As String


Get
Return mTen
End Get
Set(ByVal Value As String)
mTen = Value
End Set
End Property

Function Say() As String


Dim gio = Date.Now.Hour

Học phần 3 – VB.NET Trang 27/187


Tài liệu hướng dẫn giảng dạy

If gio >= 5 And gio <= 12 Then


Say = "Good morning, " + mTen
ElseIf gio <= 18 Then
Say = "Good afternoon, " + mTen
Else
Say = "Good evening, " + mTen
End If
End Function
End Class

Tạm thời không cần quan tâm nhiều đến cú pháp vì chúng ta sẽ tìm hiểu trong phần lập trình hướng
đối tượng. Sau khi đã viết đoạn lệnh, xem trong cửa sổ Class viewer bạn sẽ thấy các thành phần của
class SayHi được liệt kê bao gồm một thuộc tính có tên là Ten, hai phương thức là New và Say cùng với
một biến cục bộ là mTen. Thuộc tính của một class cho biết đặc điểm mà một đối tượng của nó sẽ có.
Phương thức của một class cho biết khả năng mà đối tượng của nó có thể thực hiện.

Cửa sổ Class viewer có thêm class SayHi và các thành phần của nó
Chúng ta sẽ sửa lại đoạn lệnh trong nút cmdHello để xem cách dùng một đối tượng:
Ví dụ:
Private Sub cmdHello_Click(ByVal sender As System.Object, ByVal e As _
System.EventArgs) Handles cmdHello.Click
Dim sh As SayHi, LoiChao As String
sh = New SayHi(txtTen.Text)
LoiChao = sh.Say
MsgBox(LoiChao)
End Sub

Chúng ta thấy, sử dụng class SayHi cũng giống như sử dụng class TextBox hay Label trong phần
InitializeComponent.

III.8. Sử dụng lại thành phần có sẵn


Chúng ta đã vừa tạo ra một COMponent – class SayHi. Một khi đã được tạo ra, component có thể được
sử dụng lại ở bất kỳ đâu. Chúng ta sẽ đóng gói SayHi thành một file.DLL để sử dụng trong một project
khác.
Chọn menu File | Add project | New Project … Trong cửa sổ hiện ra, gõ tên của project là SayHi và
chọn nút OK. Một project mới được đưa vào Solution cùng với một class có sẵn là Class1.
Vì chúng ta dùng project này để đóng gói class SayHi đã tạo trước đó nên hãy xoá bỏ Class1.vb bằng

Học phần 3 – VB.NET Trang 28/187


Tài liệu hướng dẫn giảng dạy

cách nhắp chuột phải và chọn mục Delete. Sau đó, đưa SayHi.vb vào project bằng cách nhắp chuột
phải trên project SayHi và chọn mục Add | Add existing item… Tìm SayHi.vb trong thư mục Hello của
project Hello và chọn Open.

Project SayHi được đưa vào Solution Explorer


Trước khi thực hiện bước đóng gói, kiểm tra lại thuộc tính của project SayHi bằng cách chọn menu
Project | Properties …

Cửa sổ Project Property Pages


Trong cửa sổ hiện ra, chúng ta sẽ thấy một số thông tin: Assembly name: SayHi, loại kết xuất (output
type): Class library. Root namespace: SayHi. Phần Information ở dưới ghi tên file kết xuất là SayHi.dll.
Đóng cửa sổ lại và biên dịch project này bằng cách chọn menu Build | Build SayHi.

Lúc này, chúng ta đã có file SayHi.dll và sẵn sàng sử dụng nó trong các ứng dụng khác. Hình dưới hiển
thị một phần cửa sổ Windows Explorer để xác định vị trí của file SayHi.dll

Kết quả biên dịch được lưu giữ trong thư mục Bin của ứng dụng
Tiếp theo đây, chúng ta sẽ xây dựng một ứng dụng console (giao diện dòng lệnh như của DOS) để sử
dụng class SayHi đã tạo ra. Chọn mục File | Close Solution để đóng solution hiện có.

Học phần 3 – VB.NET Trang 29/187


Tài liệu hướng dẫn giảng dạy

Tạo ứng dụng console


Chọn File | New project với template là Console Application. Gõ tên của project là HelloConsole và click
vào OK để tạo mới. Một project rất đơn giản được tạo ra với một file là Module1.vb. File này có nội
dung như sau:
Ví dụ:
Module Module1
Sub Main()
End Sub
End Module

Nếu lúc này chạy thử chương trình, một cửa sổ DOS sẽ nháy lên rồi biến mất. Ứng dụng chỉ chạy trong
"nháy mắt"! Chúng ta hãy thêm dòng lệnh sau trước khi nhấn lại phím F5

System.Console.ReadLine()

Khi chương trình chạy, chúng ta thấy một cửa sổ "đen ngòm" của DOS hiện ra với cursor nhấp nháy tại
góc trên bên trái. Dấu nhắc này có nghĩa ứng dụng đang chờ chúng ta nhấn phím Enter để kết thúc.
Bây giờ, hãy thực hiện bước "ghép nối" các thành phần có sẵn trong đó, thành phần ghép nối chính là
SayHi. Trong cửa sổ Solution Explorer, nhắp chuột phải trên mục Reference và chọn mục Add
reference. Chọn nút Browse và tìm file SayHi.dll. Sau khi chọn Open, chúng ta sẽ thấy mục Selected
Components liệt kê file SayHi.dll. Chọn nút OK để tham chiếu.

Học phần 3 – VB.NET Trang 30/187


Tài liệu hướng dẫn giảng dạy

Chọn tham chiếu cho ứng dụng


Lúc này, trong mục Reference liệt kê namepace SayHi:

Reference sau khi tham chiếu tập tin SayHi.dll


Cuối cùng, chúng ta "bắt vít" cho SayHi vào ứng dụng của mình:
Ví dụ:
Sub Main()
Dim sh As SayHi.SayHi
sh = New SayHi.SayHi("Nguyen Thai Hung")
System.Console.WriteLine(sh.Say)
System.Console.ReadLine()
End Sub

Khi chạy chương trình, bạn sẽ thấy cửa sổ hiện ra như bên dưới:

Cửa sổ chạy của ứng dụng console

Học phần 3 – VB.NET Trang 31/187


Tài liệu hướng dẫn giảng dạy

III.9. Assembly - một loại DLL mới


DLL (Dynamic Link Library) là một loại file thực thi trên hệ điều hành Windows dùng để chứa các thư
viện lớp đối tượng hay nói chung hơn là các Component. Một component có thể gồm 1 hay nhiều DLL.
Trong ví dụ của chúng ta, SayHi chỉ có một file DLL là SayHi.dll mà thôi.
Bằng cách tạo các component và đóng gói chúng thành các DLL, lập trình viên có thể tạo ra các thành
phần có sẵn và sử dụng lại chúng ở nhiều project khác nhau. Đơn cử một thành phần sử dụng lại
"không ai không biết" của Windows là comdlg32.dll. Đây chính là thư viện các hộp thoại dùng chung
như Open, Save, Print, Color,…
Viễn cảnh lập trình "lắp ráp" các thành phần khá tươi đẹp này có thể sẽ biến các lập trình viên thành
các "tay ghiền" đồ chơi của Lego. Tuy nhiên sử dụng những "đồ chơi" này chẳng dễ như chúng ta
tưởng. Vấn để bắt đầu ở chỗ một DLL do ai đó viết ra (chẳng hạn chính Microsoft) được nhiều phần
mềm sử dụng. Hai phần mềm A, B cài lên máy tính của chúng ta đều sử dụng DLL tên là X. Một ngày
nọ, chúng ta không dùng A nữa và gỡ bỏ (Uninstall) nó khỏi máy. Đương nhiên khi gỡ bỏ A, phần mềm
sẽ hỏi chúng ta có muốn xoá X khỏi hệ thống hay không. Thế nhưng khổ nỗi chúng ta không biết X
dùng để làm gì và có phần mềm nào khác dùng X nữa hay không. Và nếu như gỡ bỏ X, ứng dụng B
cũng hết sử dụng được.
Bây giờ giả sử rằng dung lượng ổ cứng rất nhiều và chúng ta không gỡ bỏ các DLL khỏi máy tính làm
gì. Nay chúng ta lại muốn cài đặt thêm một ứng dụng C khác nữa vào máy. C là một phần mềm mới và
nó lại sử dụng một phiên bản X mới hơn vừa cập nhật. Khi cài đặt vào máy, X mới được thay thế cho X
cũ và thế là cả A và B đều chằng hiểu gì về thành phần X mới này nên không chạy được nữa.
Câu chuyện trên không phải hiếm hoi, các lập trình viên gọi nó là “DLL Hell” hay “địa ngục DLL”. Khi
muốn bán phần mềm cho chúng ta, chính họ phải lo giải quyết vấn đề này, không chỉ với riêng những
DLL do họ viết ra và nâng cấp mới mà có khi cả những DLL của người khác nữa.
Với kỹ thuật .NET, giờ đây Microsoft đưa ra một định nghĩa mới cho DLL và cũng thay tên đổi họ cho
nó thành Assembly – thành phần lắp ráp. DLL cũ không có khả năng tự mô tả nó với hệ điều hành.
Điều này dẫn đến việc mỗi phần mềm đều phải cài đặt (install hay setup) vào hệ điều hành. Trong quá
trình này, hầu hết các DLL sẽ được copy vào thư mục của Windows nên dẫn đến việc cái này ghi đè lên
cái kia hay Windows có đủ thứ DLL trong đó. Chưa hết, các class trong DLL sẽ phải đăng ký mã số của
mình (ClassID) vào một mục để Windows quản lý gọi là Registry. Nếu trong registry bị mất một ClassID
nào đó thì Windows cũng đành chịu thua, không thể quản lý và thi hành class tương ứng được nữa.
Các Assembly xây dựng bởi .NET cũng có phần mở rộng của tập tin là .dll nhưng có khả năng tự mô tả
chính bản thân mình thông qua một thành phần chứa ngay trong tập tin .dll là Metadata. Bao lâu còn
tập tin .dll trên máy, Windows còn có khả năng đọc Metadata và thi hành các đoạn lệnh trong
assembly.
Cũng với khả năng tự mô tả chính mình, các assembly không cần phải đăng ký vào hệ thống. Điều này
nghĩa là chúng không cần phải được cài đặt bằng cách setup hay install và lưu trong thư mục Windows.
Thay vào đó, mỗi ứng dụng tự quản lý thư mục của riêng mình và lưu tập tin assembly trong đó. Việc
cài đặt ứng dụng lúc này chẳng qua là lệnh copy thư mục của DOS và nếu bạn muốn xoá ứng dụng chỉ
cần xoá thư mục của nó mà thôi.

Vì mỗi ứng dụng nằm riêng một chỗ, tự quản lý các assembly của mình nên DLL hell khó lòng xảy ra
được nữa.
Assembly được chia làm hai loại:

Học phần 3 – VB.NET Trang 32/187


Tài liệu hướng dẫn giảng dạy

– Private assembly là những assembly như mô tả ở trên nghĩa là của ứng dụng nào thì chỉ ứng dụng
đó dùng được.
– Public assembly là những assembly đem dùng chung cho nhiều ứng dụng.
Hãy xét tới trường hợp một công ty phần mềm không phải chỉ có một ứng dụng nhưng một họ các ứng
dụng cung cấp cho người dùng. Nhiều ứng dụng trong đó đều sử dụng chung một assembly. Công ty
có thể chọn hai giải pháp: dùng private assembly để mỗi ứng dụng quản lý assembly của riêng mình
hoặc, dùng public assembly để nhiều ứng dụng chỉ dùng chung một assembly mà thôi. Cách thứ hai sẽ
tiện lợi hơn cho người dùng mỗi khi họ muốn nâng cấp lên phiên bản mới của công ty.
Các assembly dùng chung được quản lý bởi Global Assembly Cache (GAC). Đây là thư mục nằm trong
thư mục Windows\Assembly\GAC. GAC quản lý các assembly này thông qua tên gọi riêng là Strong
name. Strong name được phát sinh thông qua công cụ sn.exe của .NET Framework.

Học phần 3 – VB.NET Trang 33/187


Tài liệu hướng dẫn giảng dạy

Bài 2
NGÔN NGỮ VISUAL BASIC .NET
Tóm tắt
Lý thuyết 3 tiết - Thực hành 5 tiết

Mục tiêu Các mục chính Bài tập

Đưa ra những điểm mới và những 1. Các kiểu dữ liệu và đặc điểm 1.1, 1.2, 1.3
điểm thay đổi (so với VB) trong Visual 2. Biến – Tính chất, khai báo và khởi
Basic .Net tạo
3. Mảng, Structure
4. Các toán tử
5. Cấu trúc điều khiển
6. Xử lý lỗi
7. Những thay đổi trong VB.NET

Học phần 3 – VB.NET Trang 34/187


Tài liệu hướng dẫn giảng dạy

I. Các kiểu dữ liệu và đặc điểm


I.1. Các kiểu dữ liệu
Các kiểu dữ liệu của .Net được mô tả chi tiết trong một cấu trúc gọi là Common Type System (CTS).
CTS định nghĩa các kiểu dữ liệu, cách thức sử dụng, cách thức được quản lý lúc thực thi và cùng với
Common Language Specification đóng một vai trò quan trọng trong việc trao đổi giữa các ngôn ngữ lập
trình trong .Net.
Common Type System có chức năng:
– Thiết lập một nền tảng cho phép tương tác giữa các ngôn ngữ lập trình, bảo toàn giá trị của dữ liệu
khi có sự trao đổi dữ liệu giữa các ngôn ngữ và bảo đảm việc thực hiện câu lệnh được tối ưu
– Cung cấp một mô hình hướng đối tượng cho các ngôn ngữ lập trình.
– Đưa ra những quy tắc để các ngôn ngữ lập trình phải tuân thủ nhằm bảo đảm các thành phần viết
trên các ngôn ngữ khác nhau có thể tương tác với nhau.
Các kiểu dữ liệu trong VB.NET đã có một số biến đổi cho phù hợp với các quy tắc của CTS. Dưới đây là
hệ thống các kiểu dữ liệu chính tương ứng trong Common Language Runtime:
System.Object
System.Array
System.String
System.ValueType
System.Boolean
System.Byte
System.DateTime
System.Decimal
System.Char
System.Double
System.Int16
System.Int32
System.Int64
System.Single
System.UInt16
System.UInt32
System.UInt64
Các kiểu dữ liệu nội tại của VB.NET
Kiểu VB.Net Kiểu CLR Vùng nhớ Type Miền giá trị
System.x (Byte) Code
Boolean Boolean 2 3 True hoặc False.
Byte Byte 1 6 0 đến 255 (không dấu).
Char Char 2 4 0 đến 65535 (không dấu).
DateTime DateTime 8 16 0:00:00 ngày 01 tháng Giêng 0001 đến
23:59:59 ngày 31 tháng Mười Hai 9999.
Decimal Decimal 16 15 0 đến +/-79,228,162,514,264,
337,593,543,950,335 nếu không có số lẻ;
0 đến +/-7.9228162514264337
593543950335 với 28 số lẻ; số nhỏ nhất

Học phần 3 – VB.NET Trang 35/187


Tài liệu hướng dẫn giảng dạy

khác không là +/-


0.0000000000000000000000000001 (+/-
1E-28).
Double Double 8 14 -1.79769313486231570E+308 đến -
4.94065645841246544E -324 đối với số
âm; 4.94065645841246544E-324 đến
1.79769313486231570E +308 với số
dương.
Integer Int32 4 9 -2,147,483,648 đến 2,147,483,647.
Long Int64 8 11 -9,223,372,036,854,775,808 đến
9,223,372,036,854,775,807.
Object Object 4 Bất kỳ kiểu dữ liệu nào có thể chứa trong
(Class) biến kiểu Object.
Short Int16 2 7 -32,768 đến 32,767.
Single Single 4 13 -3.4028235E+38 đến -1.401298E-45 với số
âm; 1.401298E-45 đến 3.4028235E+38 với
số dương.
String String 8 0 đến khoảng 2 tỷ ký tự Unicode
(Class)
User-Defined (kế thừa từ Mỗi thành phần của Structure có miền giá
Type ValueType) trị theo kiểu dữ liệu của thành phần.

Khi khai báo một kiểu dữ liệu cơ bản, không hẳn biến sẽ sử dụng vùng nhớ như yêu cầu lưu trữ. Ví
dụ, mảng cần thêm vùng nhớ cho chính bản thân mảng cũng như cho mỗi chiều (dimension). Mỗi biến
Object tham chiếu đến một thành phần hoặc một kiểu hỗn hợp sử dụng 4 byte vùng nhớ ngoài số vùng
nhớ cần dùng cho kiểu dữ liệu chứa trong nó.

I.2. Đặc điểm của các kiểu dữ liệu


Các kiểu dữ liệu mặc nhiên phát sinh từ lớp SysTem.Object.
Ngoài các phương thức kế thừa từ lớp SysTem.Oject, các biến kiểu dữ liệu còn có các phương thức và
thuộc tính đặc thù.
Các phương thức chung kế thừa từ SysTem.Object
– Equals: Hổ trợ việc so sánh giữa hai object.
– Finalize: Thực hiện các thao tác xóa bỏ trước khi object được tự động xóa bỏ.
– GetHashCode: Phát sinh một số tương ứng với giá trị của object.
– GetType: Trả về kiểu của object.
– ToString: Tạo ra chuỗi chứa nội dung mô tả một thể hiện của lớp.
Dưới đây là các bảng liệt kê những phương thức và thuộc tính đặc thù của các kiểu dữ liệu. Do các
phương thức có nhiều cách sử dụng khác nhau, nên trong các phần nói về phương thức chỉ mô tả công
dụng. Cần tham khảo thêm trong MSDN để hiểu rõ cách dùng.

Học phần 3 – VB.NET Trang 36/187


Tài liệu hướng dẫn giảng dạy

I.2.1. Kiểu String


Thuộc tính
Tên Mô tả
Chars(i) Trả về ký tự tại vị trí chỉ ra trong biến. Thuộc tính có tính chỉ đọc
Length Trả về số ký tự trong biến.

Phương thức
Tên Mô tả
Clone Trả về một tham chiếu của biến.
Compare Phương thức so sánh hai tham số kiểu String dựa vào thứ tự các ký tự theo ngôn
ngữ qui định trong Regional Settings của từng ký tự và trả về:
– -1 khi chuỗi thứ 1 nhỏ hơn chuỗi thứ 2
– 0 khi chuỗi thứ 1 bằng chuỗi thứ 1
– 1 khi chuỗi thứ 1 lớn hơn chuỗi thứ 2
Ngoài ra có thể có tham số qui định có phân biệt chữ Hoa chữ thường, v.v…
CompareOrdinal So sánh hai tham số kiểu String dựa theo bảng mã các ký tự của các tham số.
Hàm trả về hiệu của mã tham số thứ nhất và mã tham số thứ hai.
Concat Nối các tham số lại với nhau và trả về chuỗi nối.
Copy Tạo một thể hiện mới kiểu String có giá trị như tham số chuỗi truyền vào.
CopyTo Sao chép một số ký tự chỉ ra từ một vị trí trên biến vào một vị trí chỉ ra trên mảng
ký tự với số lượng ký tự truyền vào.
EndsWith Trả về True/False cho biết các ký tự cuối của biến có khớp với chuỗi chỉ ra không.
Format Thay thế phần biểu thức định dạng trong chuỗi bằng các các giá trị tương ứng đã
được định dạng theo biểu thức.
IndexOf Trả về vị trí đầu tiên tìm thấy chuỗi hoặc ký tự truyền vào trên biến, ; có thể sử
dụng thêm vị trí bắt đầu tìm, trả về vị trí lần tìm thấy thứ mấy.
IndexOfAny Trả về vị trí tìm thấy đầu tiên trên biến bất kỳ ký tự nào trong mảng ký tự truyền
vào; có thể sử dụng thêm vị trí bắt đầu tìm, trả về vị trí lần tìm thấy thứ mấy.
Insert Chèn vào một giá trị String truyền vào tại vị trí chỉ định trên biến.
Join Nối các phần tử của mảng String truyền vào thành một chuỗi duy nhất với dấu nối
là chuỗi dấu ngăn cách chỉ ra (separator)
LastIndexOf Trả về vị trí tìm thấy cuối cùng trên biến, chuỗi hoặc ký tự truyền vào; có thể sử
dụng thêm vị trí bắt đầu tìm, trả về vị trí lần tìm thấy thứ mấy.
LastIndexOfAny Trả về vị trí tìm thấy cuối cùng trên biến bất kỳ ký tự nào trong mảng ký tự truyền
vào; có thể sử dụng thêm vị trí bắt đầu tìm, trả về vị trí lần tìm thấy thứ mấy.
PadLeft Nối thêm bên trái ký tự truyền vào với số lần sao cho độ dài tổng cộng bằng độ
dài chỉ ra. Nếu độ dài tổng cộng chỉ ra nhỏ hơn độ dài của biến, không ký tự nào
được thêm vào.
PadRight Nối thêm bên phải ký tự truyền vào với số lần sao cho độ dài tổng cộng bằng độ
dài chỉ ra. Nếu độ dài tổng cộng chỉ ra nhỏ hơn độ dài của biến, không ký tự nào
được thêm vào.
Remove Xóa bỏ một số ký tự chỉ ra khỏi biến từ vị trí truyền vào.

Học phần 3 – VB.NET Trang 37/187


Tài liệu hướng dẫn giảng dạy

Replace Thay thế tất cả ký tự hay chuỗi tìm thấy trên biến bằng ký tự hay chuỗi truyền
vào.
Split Trả về một mảng String với các phần tử chứa các chuỗi con được ngắt ra từ biến
tùy theo ký tự ngăn cách truyền vào.
StartsWith Cho biết trị bắt đầu của biến có khớp với chuỗi truyền vào.
Substring Trả về một chuỗi con từ biến.
ToLower Trả về bản sao của biến với các ký tự in thường.
ToUpper Trả về bản sao của biến với các ký tự in HOA.
Trim Trả về biến đã loại bỏ tất cả các ký tự từ đầu đến cuối của biến khớp với mảng ký
tự truyền vào.
TrimEnd Trả về biến đã loại bỏ tất cả các ký tự từ vị trí cuối của biến khớp với mảng ký tự
truyền vào.
TrimStart Trả về biến đã loại bỏ tất cả các ký tự từ vị trí đầu của biến khớp với mảng ký tự
truyền vào.

I.2.2. Kiểu DateTime


Field
Tên Mô tả
MaxValue Hiển thị giá trị lớn nhất của kiểu DateTime (chỉ đọc).
MinValue Hiển thị giá trị nhỏ nhất của kiểu DateTime (chỉ đọc).

Thuộc tính
Tên Mô tả
Date Trả về giá trị ngày tháng năm của biến.
Day Trả về giá trị ngày trong tháng của biến.
DayOfWeek Trả về giá trị ngày trong tuần của biến, với ngày đầu tiên là Chủ nhật có giá trị là
0.
DayOfYear Trả về giá trị ngày trong năm của biến.
Hour Trả về giá trị giờ của biến.
Millisecond Trả về giá trị phần ngàn giây của biến.
Minute Trả về giá trị phút của biến.
Month Trả về tháng của biến.
Now Trả về giá trị ngày giờ hiện hành của hệ thống.
Second Trả về giá trị giây của biến.
TimeOfDay Trả về giá trị giờ phút giây của biến.
Today Trả về ngày hiện hành.
Year Trả về năm của biến.

Học phần 3 – VB.NET Trang 38/187


Tài liệu hướng dẫn giảng dạy

Phương thức
Tên Mô tả
AddDays Thêm số ngày truyền vào cho giá trị của biến.
AddHours Thêm số giờ truyền vào cho giá trị của biến.
AddMilliseconds Thêm số phần ngàn giây truyền vào cho giá trị của biến.
AddMinutes Thêm số phút truyền vào cho giá trị của biến.
AddMonths Thêm số tháng truyền vào cho giá trị của biến.
AddSeconds Thêm số giây truyền vào cho giá trị của biến.
AddYears Thêm số năm truyền vào cho giá trị của biến.
Compare So sánh hai biến ngày giờ và cho biết biến nào lớn hơn.
CompareTo So sánh biến với một tham số Object.
DaysInMonth Cho biết số ngày trong tháng theo tham số tháng, năm truyền vào.
IsLeapYear Cho biết giá trị năm truyền vào (dạng yyyy) có phải là năm nhuận hay không.
Subtract Trừ một giá trị thời gian khỏi biến.
ToLongDateString Chuyển giá trị biến ra định dạng Long Date.
ToLongTimeString Chuyển giá trị biến ra định dạng Long Time.
ToShortDateString Chuyển giá trị biến ra định dạng Short Date.
ToShortTimeString Chuyển giá trị biến ra định dạng Short Time.
ToString Trả về chuỗi trị của biến theo định dạng truyền vào

I.2.3. Kiểu Number:


Phần này nói chung cho các kiểu số Byte, Short, Integer, Long, Single, Double, Decimal

Field
Tên Mô tả
MaxValue Hiển thị giá trị lớn nhất của kiểu (chỉ đọc).
MinValue Hiển thị giá trị nhỏ nhất của kiểu (chỉ đọc).

Ngoại trừ kiểu String, các kiểu khác khi muốn chuyển sang kiểu chuỗi đều có thể dùng phương thức
ToString (kế thừa từ lớp Object) để chuyển đổi và định dạng cùng lúc.
Cú pháp sử dụng:

ToString()
ToString(<biểu thức định dạng>)

Dưới đây là bảng biểu thức định dạng

Biểu thức định dạng


Biểu thức Ý nghĩa Ví dụ
c, C Định dạng tiền tệ 12345.67 ToString(“C”) hiển thị $ 12,345.67
e, E Định dạng số khoa học. 12345.67 ToString(“E”) hiển thị 1.234567E+0004
f, F Định dạng cố định 12345.67 ToString(“F”) hiển thị 12345.67 (với 2 số lẻ)

Học phần 3 – VB.NET Trang 39/187


Tài liệu hướng dẫn giảng dạy

g, G Định dạng tổng quát 12345.67 ToString(“G”) hiển thị 12345.67 tùy theo gía trị
có thể hiện thị dưới dạng E hoặc F
n, N Định dạng số 12345.67 ToString(“N”) hiển thị 12,345.67
p, P Định dạng phần trăm 0.45 ToString(“P”) hiển thị 45 %
x, X Định dạng Thập lục phân 250 ToString(“X”) hiển thị FA

Ngoài ra chúng ta cũng có thể sử dụng các ký tự sau đây để lập biểu thức định dạng

Biểu thức định dạng tự định nghĩa


Biểu thức Ý nghĩa Ví dụ
0 Số không giữ chỗ 123 ToString(“0000”) hiển thị 0123
# Số bất kỳ giữ chỗ 123 ToString(“####”) hiển thị 123
. Dấu phần lẻ 123 ToString(“####.00”) hiển thị 123.00
, Dấu chia cụm ba số 12345 ToString(“#,###”) hiển thị 12,345
% Dấu phần trăm 0.45 ToString(“# %”) hiển thị 45 %
E+0,E- Dấu hiển thị số khoa học 12345678 ToString(“#.#######E+000”) hiển thị
0,e+0, 1.2345678E+007
e-0
\ Ký tự literal 123456 ToString(“\# #,###”) hiển thị # 123,456
; Ký tự Ký tự ngăn cách vùng Với ToString(“dương #,###;âm #,###; số không”)
ngăn -123456 hiển thị âm 123,456
cách
0 hiển thị số không
vùng

II. Biến – Tính chất, khai báo và khởi tạo


II.1. Tính chất
Biến là một thực thể với 6 tính chất sau:
– Name: Tên của biến
– Address: Địa chỉ vùng nhớ nơi lưu giữ giá trị của biến. Trong chu kỳ trình sống, địa chỉ của biến có
thể thay đổi.
– Type: Kiểu của biến, còn gọi là kiểu dữ liệu
– Value: Giá trị của biến
– Scope: Phạm vi sử dụng của biến.
Mỗi biến có một phạm vi sử dụng là phạm vi trong chương trình nơi biến được nhìn nhận đối với câu
lệnh.
ƒ Phạm vi khối lệnh và phạm vi thủ tục
Khối lệnh là tập hợp các dòng lệnh được kết thúc bằng End, Else, Loop hoặc Next như trong cấu
trúc For … Next, If...Then...Else...End If . Biến khai báo trong khối lệnh có phạm vi sử dụng chỉ
trong khối lệnh
Ví dụ:

If x <> 0 then

Học phần 3 – VB.NET Trang 40/187


Tài liệu hướng dẫn giảng dạy

Dim a as Integer
a = 1/x
End If
MsgBox CStr(a))

Đoạn lệnh trên sẽ gây lỗi tại dòng MsgBox CStr(a)) vì biến a chỉ có phạm vi sử dụng trong khối
lệnh If … End If
Khi biến được khai báo trong một thủ tục nhưng không trong một khối lệnh, biến sẽ có phạm vi
sử dụng trong toàn thủ tục. Đây là trường hợp đặc biệt của phạm vi khối lệnh với khối lệnh là
toàn bộ thủ tục.
Biến có phạm vi khối lệnh và phạm vi thủ tục là biến cục bộ.
ƒ Phạm vi module và phạm vi project
Có những khác biệt trong phạm vi sử dụng đối với các biến khai báo chung trong Module chuẩn
(Standard module) và Lớp (Class module). Trước tiên, chúng ta cần lưu ý rằng bản thân Module
chuẩn được khai báo với một trong ba từ khóa sau: Public, Friend và Private (mặc định)
Tùy theo từ khóa mà phạm vi sử dụng của các thành phần trong module bị giới hạn. Ví dụ một
biến Public khai báo trong một module Friend sẽ có phạm vi sử dụng Friend
+ Truy xuất Private
Nếu biến được khai báo trên phần Declaration của module với từ khóa Private sẽ chỉ có
phạm vi sử dụng trong module.

+ Truy xuất Friend


Nếu biến được khai báo trên phần Declaration của module với từ khóa Friend sẽ có phạm vi
sử dụng trong toàn project. Các project khác không thể sử dụng biến này.

+ Truy xuất Public


Nếu biến được khai báo trên phần Declaration của module với từ khóa Public sẽ có phạm vi
sử dụng trong toàn project và trong bất kỳ project nào bên ngoài có một tham chiếu
(reference) đến project đó.
– LifeTime: Thời gian tồn tại của biến.
Trong khi phạm vi sử dụng của biến xác định nơi chốn biến được phép sử dụng, thì thời gian tồn tại
của biến xác định khoảng thời gian biến có thể lưu giữ giá trị.
Biến có phạm vi Module có thời gian tồn tại là thời gian ứng dụng đang thực hiện.
Biến có phạm vi khối lệnh, thủ tục chỉ tồn tại trong khi thủ tục đang thực hiện. Biến này sẽ được khởi
tạo theo giá trị mặc định của kiểu dữ liệu khi thủ tục bắt đầu thực hiện và chấm dứt khi thủ tục kết
thúc.

II.2. Khai báo và khởi tạo


Lệnh khai báo biến là cú pháp kết hợp tên biến và kiểu dữ liệu. Tự thân lệnh này không hàm ý tạo
biến. Tuy nhiên, với các biến không phải kiểu đối tượng, lệnh khai báo biến cũng chính là lệnh tạo biến
Cú pháp:

Dim x as Integer

Để nhấn mạnh vai trò của hàm tạo (constructor), chúng ta có thể viết:

Học phần 3 – VB.NET Trang 41/187


Tài liệu hướng dẫn giảng dạy

Dim x as Integer = New Integer()

Khi khai báo nhiều biến trên cùng dòng và không chỉ ra kiểu của biến, biến sẽ lấy kiểu dữ liệu của biến
khai báo dữ liệu tường minh tiếp sau đó

Dim x as Integer, a, b, c as Long

Các biến a, b, c đều cùng có kiểu Long


Có thể khai báo và khởi tạo giá trị cho biến cùng lúc:

Dim x as Integer = 100, y as Integer = 200

Trong cách này, phải khai báo tường minh kiểu dữ liệu cho từng biến.
Với các biến kiểu đối tượng, cách khai báo cũng như thế

Dim objA as MyClass

Lệnh trên chưa tạo ra biến đối tượng và sau dòng lệnh, objA vẫn là Nothing
Những cách sau đây sẽ khai báo và tạo biến đối tượng:

Dim objA as New MyClass()

Hoặc

Dim objA as MyClass = New MyClass()

Hoặc

Dim objA as MyClass


objA = New MyClass()

Các từ khóa để khai báo biến

Từ khóa khai báo


Từ khóa Ý nghĩa
Public Sử dụng toàn cục
Private Sử dụng cục bộ trong phạm vi khai báo như Dim
Friend Sử dụng trong phạm vi của project
Protected Sử dụng trong phạm vi của lớp và các lớp con
Protected Friend Sử dụng trong phạm vi của Proctected và Friend

II.3. Kiểu trị và tham chiếu (Value Type và Reference Type)


Các kiểu được định nghĩa trong Common Type System thuộc ba loại sau:
– Kiểu trị (Value Type)
– Kiểu tham chiếu (Reference Type)
– Kiểu con trỏ (Pointer Type)
VB.Net không có kiểu con trỏ nên chúng ta chỉ xem xét kiểu trị và kiểu tham chiếu.
Khi một biến kiểu trị được khai báo, một vùng nhớ được dành riêng để chứa giá trị thực của biến.
Ngược lại, khi một biến kiểu tham chiếu được khai báo, trình biên dịch sẽ tạo đối tượng trên vùng nhớ,

Học phần 3 – VB.NET Trang 42/187


Tài liệu hướng dẫn giảng dạy

nhưng sẽ gán cho biến bốn byte chứa địa chỉ của đối tượng. Tóm lại, biến kiểu trị chứa giá trị của biến
còn biến kiểu tham chiếu chỉ đến nơi chứa giá trị.
Sự khác biệt này dẫn đến nhiều hệ quả mà phép gán là một. Để minh họa chúng ta xem Class sau với
một thuộc tính:

Ví dụ:

Public Class Nguoi


Public tuoi as Short
End Class

Và kiểu Structure cũng có một thuộc tính:

Structure ConNguoi
Public tuoi as Short
End Structure

Class là kiểu tham chiếu trong khi Structure là kiểu trị.


Hãy xem xét đoạn lệnh sau:

Dim Ng1, Ng2 as Nguoi


Dim CNg1, CNg2 as ConNguoi
Ng1 = New Nguoi()
Ng1.tuoi = 30
Ng2 = Ng1
Ng2.tuoi = 20
Debug.WriteLine(Ng1.tuoi) ' xuất ra 20
Debug.WriteLine(Ng2.tuoi) ' xuất ra 20
CNg1 = New ConNguoi()
CNg1.tuoi = 30
CNg2 = CNg1
CNg2.tuoi = 20
Debug.WriteLine(CNg1.tuoi)' xuất ra 30
Debug.WriteLine(CNg2.tuoi)' xuất ra 20

Khi được gán cho nhau, hai biến tham chiếu Ng1, Ng2 cùng chứa địa chỉ trỏ đến một đối tượng. Vì vậy
thay đối giá trị của thuộc tính tuoi trên biến này, thay đổi cũng phản ánh trên biến kia.
Ngược lại, khi được gán cho nhau, biến tham trị sẽ tạo nên một vùng nhớ chứa trị mới, hai biến trị
CNg1, CNg2 cùng chứa trị như nhau nhưng trên hai vùng nhớ khác nhau. Do đó, giá trị của thuộc tính
tuoi của hai biến được chứa trên hai vùng nhớ và độc lập nhau.
Chú ý: Kiểu String cũng là kiểu tham chiếu nhưng có một số đặc tính của kiểu trị.
Chúng ta xét đoạn lệnh sau:

Dim ch1, ch2 as String


ch1 = "Chuỗi 1"
ch2 = ch1

Học phần 3 – VB.NET Trang 43/187


Tài liệu hướng dẫn giảng dạy

ch2 = "Chuỗi 2"


MsgBox(ch1) ' xuất ra Chuỗi 1

Chúng ta nghĩ rằng ch1 chứa "Chuỗi 2", nhưng ch1 lại chứa "Chuỗi 1". Lý do như sau: khi biến kiểu
String đã được tạo ra, giá trị của chúng không thể sửa đổi. Sửa đổi trị của biến String là tạo ra một thể
hiện mới chứa nội dung sửa đổi. Do vậy:
– Khi gán ch2 = ch1, ch2 trỏ đến cùng một chuỗi như ch1
– Nhưng khi gán ch2 = "Chuỗi 2" do không thể thay đổi giá trị nên ch2 trỏ đến một thể hiện mới
khác với ch1
Bảng sau đây cho biết kiểu dữ liệu thuộc kiểu trị hay kiểu tham chiếu:

Phân loại
Value Type Reference Type

ƒ Các kiểu dữ liệu số ƒ Kiểu String


ƒ Kiểu Boolean, Char, Date ƒ Mảng
ƒ Kiểu Structure, ngay cả khi các thành phần ƒ Kiểu lớp đối tượng
trong Structure là kiểu tham chiếu.

II.4. Kiểu Enum (Enumeration)


Kiểu Enum là sự liên kết một tập hợp các trị hằng với các tên gợi nhớ. Các trị này mặc nhiên có kiểu
Integer và chỉ có thể là kiểu Byte, Short, Long hoặc Integer.
Kiểu Enum chỉ được tạo trong các Class hoặc Module

Cú pháp:

[Public | Protected | Friend | Protected Friend |


Private] [ Shadows ] Enum <tên> [ As <Kiểu DL>]
<tên thành phần thứ 1> [ = trị hằng 1]
<tên thành phần thứ 2> [ = trị hằng 2]
...
<tên thành phần thứ 3> [ = trị hằng 3]
End Enum

Ví dụ:

Public Enum DoTuoi as Integer


Nhidong = 0
Thieunien = 1
Thanhnien = 2
Trungnien = 3
End Enum

Khi không chỉ ra trị hằng, VB.NET sẽ gán trị cho thành phần đầu tiên là 0 và tăng dần cho các thành
phần kế tiếp:

Học phần 3 – VB.NET Trang 44/187


Tài liệu hướng dẫn giảng dạy

Ví dụ:

Public Enum DoTuoi as Integer


Nhidong ' mặc nhiên có trị 0
Thieunien ' mặc nhiên có trị 1
Thanhnien ' mặc nhiên có trị 2
Trungnien ' mặc nhiên có trị 3
End Enum

Nếu chỉ gán trị hằng cho thành phần đầu tiên, các thành phần kế tiếp sẽ nhận giá trị tăng dần:

Public Enum DoTuoi as Integer


Nhidong = 100
Thieunien ' mặc nhiên có trị 101
Thanhnien ' mặc nhiên có trị 102
Trungnien ' mặc nhiên có trị 103
End Enum

Sau khi khai báo kiểu Enum, chúng ta có thể khai báo biến kiểu Enum cũng như sử dụng các thành
phần của kiểu này thay cho các trị hằng.

Dim a As DoTuoi
a =

III. Mảng – Structure


III.1. Mảng
Mảng là tập hợp các biến có cùng kiểu dữ liệu, cùng tên nhưng có chỉ số khác nhau. Trong VB.Net,
mảng có chỉ số bắt đầu là 0 và luôn luôn là mảng động. Không như trong VB6, với VB.Net chúng ta
không được dùng từ khóa Redim để khai báo mảng nhưng chỉ được dùng để định lại kích thước mảng.
Chúng ta có các cách khai báo mảng như sau
Cú pháp:
Khai báo không khởi tạo kích thước và giá trị

Dim a() as Integer

Hoặc

Dim a as Integer()

Khai báo có khởi tạo kích thước nhưng không khởi tạo giá trị ban đầu:

Dim a(6) as Integer

Khai báo có khởi tạo kích thước và khởi tạo giá trị ban đầu:

Dim a() as Integer = {1,2,3,4,5,6,7}

Học phần 3 – VB.NET Trang 45/187


Tài liệu hướng dẫn giảng dạy

Hoặc

Dim a() as Integer = New Integer(6){1,2,3,4,5,6,7}

Hoặc

Dim a() as Integer = New Integer(6){}

Chú ý: Khi dấu { } rỗng, các phần tử có giá trị khởi tạo là giá trị mặc định của kiểu dữ liệu.
Mảng có kiểu tham chiếu nên khi gán hai biến mảng cho nhau, biến được gán sẽ là một tham chiếu
đến mảng bên phải toán tử =, khác với trong VB6, là tạo ra một mảng mới có số phần tử mang trị
giống nhau.
Mảng thuộc lớp System.Array nên có các thuộc tính và phương thức của lớp này. Sau đây là một số
thuộc tính và phương thức đáng chú ý:

Thuộc tính

Tên Mô tả
Length Số phần tử của mảng
Rank Số chiều của mảng

Phương thức

Tên Mô tả
BinarySearch Tìm kiếm trên mảng một chiều đã được sắp xếp giá trị truyền vào, sử dụng
thuật giải tìm kiếm nhị phân.
Clear Gán các phần tử trong dãy chỉ ra bằng giá trị mặc định của kiểu dữ liệu các phần
tử
Clone Trả về bản sao cạn (shallow copy) của mảng. Bản sao này chỉ sao chép kiểu trị
và kiểu tham chiếu nhưng không sao chép các đối tượng được tham chiếu đến.
Copy Sao chép một phần của mảng vào mảng khác và thực hiện chuyển đổi kiểu nếu
cần.
CopyTo Sao chép toàn bộ các phần tử của mảng một chiều vào mảng một chiều được
truyền vào bắt đầu từ vị trí chỉ ra.
GetLength Trả về số phần tử của một chiều được chỉ ra trên mảng
GetLowerBound Trả về chỉ số nhỏ nhất của một chiều được chỉ ra trên mảng
GetUpperBound Trả về chỉ số lớn nhất của một chiều được chỉ ra trên mảng
GetValue Trả về trị của một phần tử chỉ ra trên mảng
IndexOf Trả về chỉ số của phần tử đầu tiên trên mảng một chiều (hoặc trên một vùng
của mảng) trùng với giá trị truyền vào
LastIndexOf Trả về chỉ số của phần tử cuối cùng trên mảng một chiều (hoặc trên một vùng
của mảng) trùng với giá trị truyền vào
Reverse Đảo ngược thứ tự các phần tử trên mảng một chiều hoặc trên một phần của
mảng
SetValue Gán trị cho một phần tử chỉ ra trên mảng
Sort Sắp xếp các phần tử trong mảng một chiều

Học phần 3 – VB.NET Trang 46/187


Tài liệu hướng dẫn giảng dạy

III.2. Structure
Khác với mảng, Structure, kiểu do người dùng định nghĩa (UDT: User Defined Type), là một cấu trúc
gồm một hoặc nhiều thành phần có kiểu dữ liệu khác nhau. Tuy chúng ta có thể truy xuất riêng lẻ các
thành phần nhưng Structure được xem như là một thực thể duy nhất. Trong phiên bản trước, UDT
được khai báo với từ khóa Type … End Type. Trong VB.NET, cú pháp khai báo Structure như sau:

Cú pháp:

[Public|Private|Protected] Structure <tên strucure>


{Dim|Public|Private|Friend}<tên thành phần> As <kiểu dữ liệu>
...
{Dim|Public|Private|Friend}<tên thành phần N> As <kiểu dữ liệu>
End Structure

Với Structure, chúng ta được phép khai báo các phương thức.
Sau đây là các đặc điểm của Structure:
– Có các thành phần, kể cả bộ khởi tạo, phương thức, thuộc tính, hằng, sự kiện.
– Có thể cài đặt các lớp giao tiếp (Interface).
– Có thể có các bộ khởi tạo chung, có hoặc không có tham số.
– Structure là kiểu trị.
– Tất cả các thành phần của Structure mặc định là Public.
– Các thành phần của Structure không được khai báo với từ khóa Protected.
– Structure không thể kế thừa.
Mỗi Structure có một bộ khởi tạo mặc nhiên không tham số ban đầu. Bộ khởi tạo này sẽ khởi tạo mọi
thành phần dữ liệu của Structure với giá trị mặc định của chúng. Chúng ta không thể định nghĩa lại
chức năng này.
Vì Structure là kiểu trị (Value Type), nên mỗi biến Structure luôn luôn gắn liền với một thể hiện
Structure.

IV. Các toán tử


Toán tử là ký hiệu chỉ ra phép toán nào được thực hiện trên các toán hạng (có thể là một hoặc hai toán
hạng)

IV.1. Toán tử toán học


Bảng toán tử toán học
Ký hiệu Mô tả
+ (cộng)
- (trừ)
* (nhân)
/ (chia)

Học phần 3 – VB.NET Trang 47/187


Tài liệu hướng dẫn giảng dạy

\ (chia lấy phần nguyên)


Mod chia lấy phần dư của số nguyên
^ (lũy thừa)

IV.2. Toán tử nối chuỗi


Toán tử chỉ dành cho toán hạng kiểu String với hai toán tử là & (ampersand) và + (cộng). Kết quả là
một trị String gồm các ký tự của toán hạng thứ nhất tiếp theo sau là các ký tự của toán hạng thứ hai

IV.3. Toán tử gán


Bảng toán tử gán
Ký hiệu Mô tả
= Gán toán hạng thứ hai cho toán hạng thứ nhất
+= Cộng hoặc nối chuỗi toán hạng sau vào toán hạng đầu và gán kết quả cho toán
hạng đầu
-= Trừ toán hạng sau khỏi toán hạng đầu và gán hiệu cho toán hạng đầu
*= Nhân hai toán hạng với nhau và gán tích cho toán hạng đầu
/= Chia toán hạng đầu cho toán hạng sau và gán thương cho toán hạng đầu
\= Thực hiện phép toán \ giữa toán hạng đầu và toán hạng sau và gán kết quả cho
toán hạng đầu
^= Tính lũy thừa toán hạng đầu với số mũ là toán hạng sau và gán kết quả cho
toán hạng đầu
&= Nối chuỗi toán hạng sau vào toán hạng đầu và gán kết quả cho toán hạng đầu

IV.4. Toán tử so sánh


Bảng toán tử so sánh

Ký hiệu Mô tả
= Bằng
>= Lớn hơn hoặc bằng
<= Nhỏ hơn hoặc bằng
> Lớn hơn
< Nhỏ hơn
<> Khác
TypeOf … Is … So sánh kiểu của biến kiểu tham chiếu thứ nhất có trùng kiểu trên toán hạng thứ
hai, nếu trùng trả về True, ngược lại False
Is Toán tử dành cho toán hạng kiểu tham chiếu, trả về True nếu hai toán hạng
cùng tham chiếu đến một đối tượng, ngược lại là False)
Like Toán tử dành cho toán hạng kiểu String, trả về True nếu toán hạng thứ nhất
trùng với mẫu (pattern) của toán hạng thứ hai, ngược lại là False.
Ví dụ:

Học phần 3 – VB.NET Trang 48/187


Tài liệu hướng dẫn giảng dạy

Dim kiem_tra As Boolean


kiem_tra = "F" Like "F" Æ True.
kiem_tra = "F" Like "f" Æ False.
kiem_tra = "F" Like "FFF" Æ False.
kiem_tra = "aBBBa" Like "a*a" ( True. (bắt đầu và kết thúc chuỗi là ký tự a, ở
giữa là số ký tự bất kỳ)
kiem_tra = "F" Like "[A-Z]" ( True. (giá trị trong dãy từ A đến Z)
kiem_tra = "F" Like "[!A-Z]" Æ False.
kiem_tra = "a2a" Like "a#a" ( True. (bắt đầu và kết thúc chuỗi là ký tự a, ở
giữa là một ký số)
kiem_tra = "aM5b" Like "a[L-P]#[!c-e]" Æ True.
kiem_tra = "BAT123khg" Like "B?T*" Æ True.
kiem_tra = "CAT123khg" Like "B?T*" Æ False.

IV.5. Toán tử luận lý và Bitwise


Toán tử luận lý trả về giá trị True/False

Bảng toán tử gán


Ký hiệu Mô tả
Not Trả về giá trị ngược lại của toán hạng
And Trả về True (1) khi và chỉ khi hai toán hạng cùng là True (1)
AndAlso Trả về giá trị như And nhưng khi toán hạng thứ nhất là False (0) sẽ không kiểm
tra toán hạng thứ hai và trả về False
Or Trả về False (0) khi và chỉ khi hai toán hạng cùng là False (0)
OrElse Trả về giá trị như Or nhưng khi toán hạng thứ nhất là True (1) sẽ không kiểm
tra toán hạng thứ hai và trả về True (1)
Xor Trả về True (1) khi và chỉ khi có 1 toán hạng là True (1)
Not Trả về giá trị ngược lại của toán hạng

V. Cấu trúc điều khiển


V.1. Cấu trúc chọn
V.1.1. If … Then … Else
Trước tiên, chúng ta làm quen với cấu trúc If … Then … End If
Cú pháp:

If <điều kiện> Then


' Các câu lệnh
End if

Sử dụng cú pháp này, người lập trình muốn khai báo với trình biên dịch rằng các câu lệnh trong vùng If
… End If chỉ được thực hiện nếu như <điều kiện> là đúng.

Học phần 3 – VB.NET Trang 49/187


Tài liệu hướng dẫn giảng dạy

<điều kiện> có thể là biểu thức trả về giá trị True/False hoặc là một giá trị số. Giá trị số <> 0 tương
ứng với True, ngược lại là False.
Cấu trúc If … Then … End If còn thiếu sót vì đôi khi chúng ta muốn thực hiện các câu lệnh khác khi
điều kiện không đúng. Lúc này, chúng ta sử dụng cấu trúc sau:

Cú pháp:

If <điều kiện> Then


' Các lệnh sẽ thực hiện nếu điều kiện đúng
End If
If Not <điều kiện> Then
' Các lệnh sẽ thực hiện nếu điều kiện sai
End If

Để thay thế cách viết trên, chúng ta có cấu trúc sau:

If <điều kiện> Then


' Các câu lệnh khi điều kiện đúng
Else
' Các câu lệnh khi điều kiện sai
End if

Trong trường hợp nhiều điều kiện, chúng ta sử dụng cấu trúc:

If <điều kiện 1> Then


...
ElseIf <điều kiện 2> Then
...
ElseIf <điều kiện n> Then
...
Else
...
End If

Ghi chú: Các mệnh đề If … Then … Else có thể lồng nhau.

V.1.2. Select … Case


Khi có nhiều trường hợp cần xét, có thể sử dụng cấu trúc chọn Select … Case với cú pháp
Cú pháp:

Select Case <biểu thức>


Case <giá trị 1>
' Các lệnh thực hiện khi <biểu thức> = <giá trị 1>
Case <giá trị 2>
' Các lệnh thực hiện khi <biểu thức> = <giá trị 2>
Case Else

Học phần 3 – VB.NET Trang 50/187


Tài liệu hướng dẫn giảng dạy

' Các lệnh thực hiện khi <biểu thức> không bằng giá trị nào ở trên
End Select

Khối lệnh Case Else có thể không cần viết. Tuy nhiên, người lập trình được khuyến khích dùng khối
lệnh này trong cấu trúc để giảm bớt các lỗi logic.
Các giá trị dùng để so sánh có thể gồm nhiều giá trị phân biệt bởi dấu phẩy (,) hoặc là một phần của
biểu thức so sánh.

V.2. Cấu trúc lặp


Cấu trúc lặp cho phép thực hiện nhiều lần một khối lệnh của chương trình. Các cấu trúc lặp thường
được sử dụng trong Visual Basic.NET gồm:

V.2.1. For … Next


Cú pháp:

For <biến đếm> = <giá trị đầu> To <giá trị cuối> [Step <bước>]
' Các câu lệnh
Next [biến đếm]

– Các câu lệnh trong vùng For … Next chỉ được thực hiện nếu <biến đếm> có giá trị trong đoạn
[<giá trị đầu>, <giá trị cuối>]
– Sau mỗi lần thực hiện, <biến đếm> sẽ được tăng thêm <bước>. Nếu không chỉ định, <bước> có
giá trị là 1.
– Nếu <bước> có trị > 0, cấu trúc chỉ thực hiện khi <giá trị đầu> <= <giá trị cuối>
– Nếu <bước> có trị < 0, cấu trúc chỉ thực hiện khi <giá trị đầu> >= <giá trị cuối>

V.2.2. For Each … Next


Cú pháp:

For Each <phần tử> In <tập hợp>


' Các câu lệnh
Next [phần tử]

Với cú pháp này, chương trình sẽ duyệt qua từng phần tử trong tập hợp đang duyệt.
Cần khai báo biến <phần tử> là kiểu của phần tử trong tập hợp đang duyệt. Chúng ta có thể chấm dứt
lặp khi đang giữa vòng lặp bằng lệnh Exit For

V.2.3. Do While … Loop


Cú pháp:

Do While <biểu thức logic>


' Các câu lệnh
Loop

Với cú pháp này, các câu lệnh đặt trong vùng Do While … Loop chỉ thực hiện bao lâu <biểu thức logic>
có giá trị True.
Sau mỗi lần thực hiện các câu lệnh trong vùng Do While...Loop, <biểu thức logic> sẽ được kiểm tra lại:

Học phần 3 – VB.NET Trang 51/187


Tài liệu hướng dẫn giảng dạy

– Nếu trị True, thực hiện lại vòng lặp


– Nếu trị False, chấm dứt vòng lặp.
Cấu trúc này kiểm tra <biểu thức logic> trước khi thực hiện các lệnh nên sẽ không thực hiện lần nào
nếu ngay lần đầu tiên <biểu thức logic> có trị False.

V.2.4. Do … Loop While


Cú pháp:

Do
' Các câu lệnh
Loop While <biểu thức logic>

Tương tự Do While … Loop, các câu lệnh chỉ tiếp tục thực hiện khi <biểu thức logic> có giá trị True và
sẽ kiểm tra lại <biểu thức logic> sau mỗi lần thực hiện.
Do kiểm tra sau khi thực hiện nên nếu ngay lần đầu <biểu thức logic> có trị False, các lệnh cũng được
thực hiện một lần.
Chúng ta có thể chấm dứt giữa chừng vòng lặp với lệnh Exit Do

V.2.5. Do Until … Loop


Cú pháp:

Do Untile <biểu thức logic>


' Các câu lệnh
Loop

V.2.6. Do … Loop Until


Cú pháp:

Do
' Các câu lệnh
Loop Until <biểu thức logic>

Hai cú pháp nầy tương tự hai cú pháp trên (Do While … Loop, Do … Loop While), với một khác biệt là
chỉ thực hiện hoặc tiếp tục thực hiện khi <biểu thức logic> là False.

V.2.7. While … End While


Cú pháp khác so với trong các phiên bản trước (While … Wend), cách sử dụng như Do While … Loop

VI. Những thay đổi trong VB.NET


VI.1. Thay đổi trong thủ tục và hàm
– Tham số là tham trị
Tham số truyền cho hàm hoặc thủ tục mặc định là tham trị ByVal chứ không phải ByRef như trong VB6.
Trong VB6, tham số ParamArray vốn được truyền theo kiểu tham chiếu ByRef và không thể thay đổi
thành ByVal nhưng trong VB.NET là tham trị ByVal và không thể thay đổi thành ByRef.

Học phần 3 – VB.NET Trang 52/187


Tài liệu hướng dẫn giảng dạy

– Tham số tùy chọn


Tham số tùy chọn Optional phải khai báo giá trị mặc nhiên, khi không truyền tham số.
Ví dụ:

Sub TEST(ByVal a As Integer,Optional ByVal c As Boolean = False)


' Các câu lệnh
End Sub

– Cách hàm trả về giá trị


Giá trị của hàm có thể trả về qua dòng lệnh Return.

Function TESTFUNCTION(ByVal a As Short, ByVal c As Short) As Integer


' Các câu lệnh
Return <giá trị trả về>
End Function

– Cho phép nhiều hàm, thủ tục trùng tênị


Có thể có nhiều hàm và thủ tục trùng tên nhau (Overloaded) miễn là số tham số hoặc kiểu dữ liệu
tham số khác nhau.
Ví dụ:

Function BinhPhuong(ByVal so As Integer) As Integer


Return Convert.ToInt32(so^2)
End Function

Function BinhPhuong(ByVal so As Double) As Double


Return so^2
End Function

Trong VB6, nếu tham số truyền vào là thuộc tính của một đối tượng cho thủ tục kiểu ByRef, những
thay đổi trên tham số đó trong thủ tục không phản ánh trên thuộc tính. Ngược lại, trong VB.NET, các
thay đổi như vậy đều thể hiện trên thuộc tính của đối tượng.

VI.2. Khai báo Option Strict


Khai báo Option Strict On|Off là một lệnh mới không cho phép các chuyển đổi kiểu làm mất dữ liệu.
Nhưng chúng ta có thể thực hiện các chuyển đổi mở rộng như chuyển biến kiểu Integer sang kiểu
Long. Khai báo này (khi bật On) sẽ không cho phép tự động chuyển đổi kiểu chuỗi sang kiểu số hay
ngược lại.
Ví dụ:

Option Strict On
--------------------------
Dim x As String, y As Integer
' x = y sẽ gây lỗi cú pháp
' nhưng phải dùng
x = CStr(y)

Học phần 3 – VB.NET Trang 53/187


Tài liệu hướng dẫn giảng dạy

' hoặc
x = y.ToString

VI.3. Kiểu chuỗi có độ dài cố định


Kiểu chuỗi có độ dài cố định trong VB6 không còn được hỗ trợ trong VB.NET

VI.4. Chỉ thị #Region … #End Region


Chỉ thị #Region … #End Region được dùng để đánh dấu một khối lệnh có thể thu gọn, giản ra trên cửa
sổ viết lệnh.

Cú pháp:

#Region <chuỗi định danh>


' khối lệnh
#End Region

<chuỗi định danh>: bắt buộc, có giá trị kiểu String, là tiêu đề của khối lệnh
Ví dụ:

#Region "Các khai báo"


' Đưa vào các dòng lệnh khai báo.
#End Region

Khi thu lại:

+ Các khai báo

VI.5. Imports không gian tên (Namespace)


Mục đích của lệnh Imports là để đưa không gian tên vào trong Module cho việc khai báo và tạo các lớp
trong không gian tên ngắn gọn hơn.
Cú pháp:

Imports [<bí danh> = ]<không gian tên> [.<thành phần>]

<bí danh>: tùy chọn, kiểu String, là tên tắt của <Namespace> được sử dụng trong tham chiếu trên
Module, Class. Nếu lệnh Imports không có phần bí danh, các thành phần định nghĩa trong không gian
tên có thể được truy cập mà không cần chỉ rõ. Nếu có bí danh, bí danh phải được sử dụng trong phần
truy cập.
<không gian tên>: bắt buộc, không gian tên sử dụng trong Module, Class
<thành phần>: tùy chọn, tên của một thành phần đã được khai báo trong không gian tên. Nó có thể là
định danh, structure, class…

Chú ý
– Mỗi lệnh Imports chỉ được sử dụng với một không gian tên.
– Mỗi Module có thể có nhiều dòng Imports
– Các lệnh Imports phải được đặt trước tất cả các khai báo, kể cả lệnh khai báo Module hoặc Class.
– Sau lệnh Imports, các thành phần được tham chiếu không cần phải chỉ ra nội dung phần Imports

Học phần 3 – VB.NET Trang 54/187


Tài liệu hướng dẫn giảng dạy

– Không được phép định nghĩa một thành phần ở cấp Module cùng tên với bí danh đã đặt

Ví dụ:

Imports Str = Microsoft.VisualBasic.String


Class lopVidu
Sub Chao()
MessageBox.Show(Str.Left("Chào bạn", 5))
End Sub
End Class

VII. Xử lý lỗi
VII.1. Phân loại lỗi
Trong VB.NET, chúng ta có thể gặp các loại lỗi sau:

VII.1.1. Syntax error


Lỗi cú pháp, còn gọi là lỗi trong lúc thiết kế. Những lỗi này dễ chỉnh sửa vì VB.NET sẽ kiểm tra cú pháp
khi ta đang nhập từ bàn phím nên sẽ báo lỗi tức thời khi ta gõ sai hoặc dùng một từ không thích hợp.

VII.1.2. Run-time error


Lỗi thực thi xảy ra khi chương trình đang thực thi. Đây là những lỗi khó xác định hơn lỗi cú pháp. Lỗi
thực thi có thể từ các lý do khác nhau như:
– Mở một tập tin không tồn tại
– Truy xuất một thư mục nhưng không có quyền trên đó
– Truy xuất dữ liệu một bảng không tồn tại trong CSDL
– Chia cho số 0
– Nhập chuỗi cho nơi cần nhập số hoặc ngược lại, v.v…

VII.1.3. Logic error


Lỗi luận lý cũng xảy ra khi chương trình đang thực thi và được thể hiện dưới những hình thức hay
những kết quả không mong đợi. Loại lỗi này thường do sai lầm trong thuật giải.

VII.2. Xử lý lỗi
Một lỗi xảy ra khi chương trình đang chạy gọi là một Exception. Trong CLR, Exception là một đối tượng
từ lớp System.Exception. Chúng ta cần lưu ý một lỗi xảy ra trong lúc thực thi không làm treo chương
trình, nhưng nếu không được xử lý sẽ làm treo chương trình. CLR chỉ ra tình trạng lỗi qua lệnh Throw.
Lệnh này sẽ đưa ra một đối tượng kiểu System.Exception chứa thông tin về lỗi đang xảy ra.
Trước đây, chúng ta thường sử dụng cú pháp On Error Goto <nhãn lỗi> để xử lý lỗi. Đây là một loại xử
lý không cấu trúc vì kể từ dòng lệnh On Error Goto <nhãn lỗi> đến cuối thủ tục hay hàm, nếu dòng
lệnh nào gây lỗi chương trình đều nhường quyền xử lý cho đoạn lệnh của <nhãn lỗi>. Với VB.NET,
chúng ta phát hiện và xử lý lỗi một cách chặt chẽ với cú pháp

Học phần 3 – VB.NET Trang 55/187


Tài liệu hướng dẫn giảng dạy

Cú pháp:

Try
' các lệnh có khả năng gây lỗi
Catch
' các lệnh xử lý khi lỗi xảy ra
[Finally]
' các lệnh thực hiện sau cùng
End Try

Cấu trúc này cho phép chúng ta thử (Try) thực hiện một khối lệnh xem có gây lỗi không; nếu có sẽ bẫy
và xử lý (Catch) lỗi.
Cấu trúc này chia làm các khối sau:

– Khối Try:
Chứa các câu lệnh có khả năng gây lỗi
– Khối Catch:
Các dòng lệnh để bẫy và xử lý lỗi phát sinh trên khối Try. Khối này gồm một loạt các lệnh bắt đầu
với từ khóa Catch, biến kiểu Exception ứng với một kiểu Exception muốn bẫy và các lệnh xử lý. Dĩ
nhiên, chúng ta có thể dùng một lệnh Catch cho các System.Exception, nhưng như thế sẽ không
cung cấp thông tin đầy đủ cho người dùng về lỗi đang xảy ra cũng như hướng dẫn cách xử lý cụ
thể cho mỗi tình huống. Ngoài những lỗi đã xử lý, có thể xảy ra những lỗi ngoài dự kiến, để xử lý
các lỗi này, chúng ta nên đưa thêm một lệnh Catch để bẫy tất cả các trường hợp còn lại và xuất
thông tin về lỗi xảy ra.
– Khối Finally:
Khối tùy chọn, sau khi chạy qua các khối Try và Catch nếu không có chỉ định nào khác, khối Finally
sẽ được thực hiện bất kể có xảy ra lỗi hay không.
Cuối cùng, cấu trúc bẫy và xử lý lỗi chấm dứt với từ khóa End Try.
Cú pháp chung cho một cấu trúc xử lý lỗi như sau

Try
' khối lệnh có thể gây lỗi
Catch <biến1> As <Kiểu Exception> [When <biểu thức>]
' khối lệnh bẫy và xử lý lỗi
Catch <biến2> As <Kiểu Exception> [When <biểu thức>]
' khối lệnh bẫy và xử lý lỗi
Finally
' khối lệnh kết thúc
End Try

Ví dụ:

Dim d as Double, i as Integer


Try
i = CInt(InputBox(“Xin nhập một số nguyên”))
d = 42 \ i

Học phần 3 – VB.NET Trang 56/187


Tài liệu hướng dẫn giảng dạy

Catch ex As DivideByZeroException
Messagebox.Show(“Không thể chia cho số không”)
Catch ex As InvalidCastException
Messagebox.Show(“Xin nhập số nguyên !”)
End Try

Câu lệnh Catch có thể có nhiều cách sử dụng:

VII.2.1. Bẫy không có điều kiện


Dim d as Double, i as Integer
Try
i = CInt(InputBox(“Xin nhập một số nguyên”))
d = 42 \ i
Catch
Messagebox.Show(“Không thể chia")
End Try

VII.2.2. Bẫy với kiểu lỗi chung Exception


Dim d As Double, i As Integer
Try
i = InputBox("Xin nhập một số nguyên")
d = 42 \ i
Catch ex As Exception
MessageBox.Show("Không thể chia")
End Try

VII.2.3. Bẫy với những kiểu Exception đặc biệt


Các kiểu Exception đặc biệt thường gặp

Bảng liệt kê các Exception


Tên Mô tả
ArgumentException Tham số truyền không hợp lệ
DivideByZeroException Chương trình thực hiện phép chia một số cho số không
OverFlowException Kết quả của một phép toán hoặc của một phép chuyển đổi kiểu lớn hơn
khả năng lưu giữ của biến
FieldAccessException Chương trình truy xuất một field Private hoặc Protected của lớp
InvalidCastException Chương trình đang cố thực hiện một chuyển đổi không hợp lệ
InvalidOperationException Chương trình đang cố gọi một thủ tục không hợp lệ
MemberAccessException Truy xuất một thành phần của một lớp bị thất bại
MethodAccessException Chương trình đang cố gọi thủ tục Private hoặc Protected của lớp
NullReferenceException Chương trình đang cố truy xuất một đối tượng không tồn tại
TypeUnloadException Chương trình truy xuất một lớp chưa được tải lên vùng nhớ

Học phần 3 – VB.NET Trang 57/187


Tài liệu hướng dẫn giảng dạy

VII.2.4. Bẫy với điều kiện When


Dim d As Double, i As Integer
Try
i = InputBox("Xin nhập một số nguyên")
d = 42 \ i
Catch ex As Exception When i = 0
MessageBox.Show("Không thể chia cho số không")
End Try

Học phần 3 – VB.NET Trang 58/187


Tài liệu hướng dẫn giảng dạy

Bài 3
LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG
TRONG VISUAL BASIC .NET
Tóm tắt
Lý thuyết 6 tiết - Thực hành 10 tiết

Mục tiêu Các mục chính Bài tập

Giới thiệu về Lập trình hướng đối 1. Lập trình hướng đối tượng 2.1, 2.2, 2.3, 2.4,
tượng và cách xây dựng lớp đối 2. Lập trình hướng đối tượng trong 2.5
tượng trong Visual Basic .Net VB.NET

Học phần 3 – VB.NET Trang 59/187


Tài liệu hướng dẫn giảng dạy

I. Lập trình hướng đối tượng


Tư tưởng chính của lập trình hướng đối tượng là xây dựng một chương trình dựa trên sự phối hợp hoạt
động của các đối tượng. Một đối tượng bao gồm hai thành phần chính là thông tin lưu trữ và các thao
tác xử lý. Trong thế giới thực, đối tượng là thực thể tồn tại như con người, xe, máy tính, v.v…Trong
ngôn ngữ lập trình, đối tượng có thể là màn hình, điều khiển v.v…

Lập trình hướng đối tượng là kiểu lập trình nhằm vào sự tương tác giữa các đối tượng. Mỗi đối tượng
có những thuộc tính (thông tin lưu trữ), những phương thức xác định các chức năng của đối tượng.
Bên cạnh đó, đối tượng cũng có khả năng phát sinh các sự kiện khi thay đổi thông tin, thực hiện một
chức năng hay khi đối tượng khác tác động vào. Tất cả những thuộc tính, phương thức và sự kiện tạo
nên cấu trúc của đối tượng. Có bốn ý niệm trong Lập trình hướng đối tượng:
– Abstraction: Tính trừu tượng
– Encapsulation: Tính bao bọc
– Inheritance: Tính kế thừa
– Polymorphism: Tính đa hình
Mỗi ý niệm đều có vai trò quan trọng trong lập trình hướng đối tượng.

I.1. Tính trừu tượng


Chúng ta thường lẫn lộn giữa lớp (Class) và đối tượng (Object). Cần phân biệt lớp là một ý niệm trừu
tượng, còn đối tượng là một thể hiện của lớp.
Ví dụ:
Class ConNgười là một ý niệm trừu tượng, nhưng NguyễnVănA là một đối tượng cụ thể.
Từ những đối tượng giống nhau, chúng ta có thể trừu tượng hóa thành một lớp đối tượng.
Tính trừu tượng cho phép chúng ta loại bỏ tính chất phức tạp của đối tượng bằng cách chỉ đưa ra các
thuộc tính và phương thức cần thiết của đối tượng trong lập trình.

I.2. Tính bao bọc


Mỗi Class được xây dựng để thực hiện một nhóm chức năng đặc trưng của riêng Class, trong trường
hợp một đối tượng thuộc Class cần thực hiện một chức năng không nằm trong khả năng vì chức năng
đó thuộc về một đối tượng thuộc Class khác, nó sẽ yêu cầu đối tượng đó đảm nhận thực hiện công
việc. Một điểm quan trọng trong cách giao tiếp giữa các đối tượng là một đối tượng sẽ không được truy
xuất trực tiếp vào thành phần dữ liệu của đối tượng khác cũng như không đưa thành phần dữ liệu của
mình cho đối tượng khác một cách trực tiếp. Tất cả mọi thao tác truy xuất vào thành phần dữ liệu từ
đối tượng này qua đối tượng khác phải được thực hiện bởi các phương thức (method) của chính đối
tượng chứa dữ liệu. Đây cũng chính là một tính chất quan trọng trong lập trình hướng đối tượng gọi là
tính bao bọc (encapsulation) dữ liệu.
Tính bao bọc cho phép dấu thông tin của đối tượng bằng cách kết hợp thông tin vớiø các phương thức
liên quan đến thông tin trong đối tượng.

Ví dụ:
Xe hơi có các chức năng (phương thức phô diễn bên ngoài) như Ngừng, Chạy tới, Chạy lùi. Đây là

Học phần 3 – VB.NET Trang 60/187


Tài liệu hướng dẫn giảng dạy

những gì cần thiết cho Tài xế khi tương tác với Xe hơi. Xe hơi có thể có một đối tượng Động cơ nhưng
Tài xế không cần phải quan tâm. Tất cả những gì cần quan tâm là những chức năng để có thể vận
hành xe. Do đó, khi thay một Động cơ khác, Tài xế vẫn sử dụng các chức năng cũ để vận hành Xe hơi
bao lâu các phương thức phô diễn bên ngoài (Interface) không bị thay đổi.

I.3. Tính kế thừa


Tính kế thừa là khả năng cho phép ta xây dựng một lớp mới dựa trên các định nghĩa của một lớp đã
có. Lớp đã có gọi là lớp Cha, lớp mới phát sinh gọi là lớp Con và đương nhiên kế thừa tất cả các thành
phần của lớp Cha, có thể mở rộng công năng các thành phần kế thừa cũng như bổ sung thêm các
thành phần mới
Chúng ta phân biệt hai loại quan hệ:

I.3.1. Là-một
Biểu thị tính kế thừa. Trong quan hệ "là-một", một đối tượng của lớp Con được xem như là một đối
tượng của lớp Cha.

Xe

Xe hơi

Ví dụ:
Từ lớp Xe ta tạo nên lớp Xe hơi mở rộng, lớp này mặc nhiên kế thừa tất cả các thành phần của lớp xe.
Ta có thể nói: một xe hơi là một chiếc xe.

I.3.2. Có-một
Quan hệ này mang ý nghĩa gồm có. Trong quan hệ "có-một", một đối tượng có thể có một hoặc nhiều
thành phần tham chiếu đến các đối tượng khác.
Ví dụ:
Khi lập mô hình loại xe hơi, bạn muốn diễn tả ý tưởng chiếc xe "có-một" tay lái. Chúng ta không thể
phát sinh lớp Xe hơi từ một Tay lái hay ngược lại (một Xe hơi "là-một" Tay lái !!!). Thay vì vậy, chúng
ta phải có hai lớp độc lập làm việc với nhau trong đó, lớp phía ngoài (lớp Xe hơi) sẽ tạo và phô diễn
công năng của lớp phía trong (lớp Tay lái).

I.4. Tính đa hình


Tính đa hình là khả năng một ngôn ngữ xử lý các đối tượng hữu quan theo cùng một cách.

Tính đa hình thể hiện dưới nhiều hình thức:

I.4.1. Kết nối trễ - Late Binding


Đây là khả năng cho phép người lập trình gọi trước một phương thức của đối tượng, tuy chưa xác định
được đối tượng. Đến khi thực hiện, chương trình mới xác định được đối tượng và gọi phương thức
tương ứng của đối tượng đó. Kết nối trễ giúp chương trình được uyển chuyển chỉ yêu cầu đối tượng
cung cấp đúng phương thức cần thiết là đủ.
Ví dụ:

Học phần 3 – VB.NET Trang 61/187


Tài liệu hướng dẫn giảng dạy

Chúng ta có lớp Xe với phương thức Chạy và các lớp Xe đạp, Xe hơi, Xe đẩy cùng phát sinh từ lớp Xe.
Chúng ta chưa biết sẽ sử dụng xe gì để di chuyển vì tùy thuộc tình hình có sẵn xe nào nên gọi trước
phương thức Chạy. Khi chương trình thực thi, tùy theo đối tượng của lớp nào được đưa ra mà phương
thức Chạy của đối tượng đó được gọi.

I.4.2. Nạp chồng - Overloading


Khả năng cho phép một lớp có nhiều thuộc tính, phương thức cùng tên nhưng với các tham số khác
nhau về loại cũng như về số lượng. Khi được gọi, dựa vào tham số truyền vào, thuộc tính hay phương
thức tương ứng sẽ được thực hiện.

I.4.3. Ghi chồng - Overriding


Hình thức này áp dụng cho lớp Con đối với lớp Cha. Lớp Con được phép có một phương thức cùng tên,
cùng số tham số có kiểu dữ liệu như phương thức của lớp Cha hoặc những lớp trước đó nữa (lớp phát
sinh ra lớp Cha …) với cài đặt khác đi. Lúc thực thi, nếu lớp Con không có phương thức riêng, phương
thức của lớp Cha sẽ được gọi, ngược lại nếu có, phương thức của lớp Con được gọi.

II. Lập trình hướng đối tượng trong VB.NET


II.1. Tạo một Class
Chúng ta tạo một Class mới trong VB.NET bằng cách dùng thực đơn Project | Add Class. Hộp thoại Add
New Item sẽ hiện ra, chọn Class trên khung bên phải và nhập tên vào ô Name bên dưới

Mã lệnh của Class nầy sẽ được chứa trong một tập tin có phần mở rộng là vb. Trong VB.NET tất cả các
tập tin nguồn của các đối tượng form, class, module …đều có phần mở rộng là vb. Hệ thống sẽ nhận
diện ra loại nào tùy theo nội dung của chúng chứ không dựa vào phần mở rộng.

Nhấn OK, để xác nhận tạo tập tin, tập tin sẽ được tạo và đưa vào Project. Lúc này trên cửa sổ mã lệnh
của Class chứa các dòng sau:

Public Class <tên Class>


End Class

Học phần 3 – VB.NET Trang 62/187


Tài liệu hướng dẫn giảng dạy

Chúng ta có thể khai báo một lớp với cú pháp sau


Cú pháp:

[<Từ khoá>] Class <tên Class>


End Class

Mọi thuộc tính, phương thức hoặc sự kiện của Class được tạo ra phải nằm trong hai dòng lệnh trên.
Từ khóa có thể là một trong các giá trị ở bảng sau:

Các từ khóa khai báo Class


Tên Mô tả
Public Các thực thể khai báo với từ khóa này có thể sử dụng ở mọi nơi.
Private Cho biết thực thể khai báo chỉ được sử dụng trong phạm vi khai báo.
Protected Cho biết thực thể khai báo chỉ được sử dụng trong phạm vi Class và SubClass
(lớp và lớp con).
Friend Cho biết thực thể khai báo chỉ được sử dụng trong phạm vi Project. Nếu không
có từ khóa, Class mặc nhiên là khai báo Friend.
Protected Friend Cho biết thực thể khai báo có phạm vi sử dụng của Protected và Friend.
Shadows Cho biết lớp này đang che mờ một thành phần trong lớp cơ sở. Thành phần bị
che mờ không thể sử dụng trong lớp này.
MustInherit Cho biết các thành phần non-shared của lớp chỉ có thể truy xuất thông qua các
lớp kế thừa. Các thể hiện của lớp khai báo kiểu này không thể khởi tạo.
NotInheritable Cho biết lớp này không cho phép kế thừa.

II.2. Tạo một NameSpace mới


Trong một tập tin như trên có thể chứa nhiều Class khác nhau.
Chúng ta có thể tổ chức các Class cùng loại, cùng nhóm vào chung một không gian tên (NameSpace)
do chúng ta tạo ra.
Ví dụ:

Namespace Dong_vat
Public Class An_co
End Class

Public Class An_thit


End Class
End Namespace

Để tham chiếu đến một Class được khai báo trong Namespace, chúng ta phải thông qua tên
Namespace.
Ví dụ:

Private conbo as Dongvat.Anco

Học phần 3 – VB.NET Trang 63/187


Tài liệu hướng dẫn giảng dạy

Một không gian tên có thể xuất hiện trong nhiều tập tin Class khác nhau trong một Project.
Ví dụ ta có tập tin thứ hai với nội dung:

Namespace Dong_vat
Public Class An_tap
End Class
End Namespace

Và cùng có chung cách tham chiếu thông qua không gian tên:

Private conbo as Dongvat.

II.3. Tạo một Class kế thừa


Khi tạo một Class kế thừa, chúng ta sẽ có một Class mới kế thừa tất cả các thành phần đã được khai
báo với từ khóa Public, Friend và Protected của Class được kế thừa. Cú pháp tạo Class kế thừa như
sau:
Cú pháp:

Public Class <tên Class con>


Inherits <tên Class cha>
End Class

Chú ý: Lệnh Inherits phải là dòng đầu tiên sau dòng lệnh khai báo Class.

II.4. Khai báo phương thức (Method)


Phương thức là chức năng mà đối tượng có thể thực hiện, nó có thể là một thủ tục (Sub) hoặc một
hàm (Function). Với hàm, phải có giá trị trả về.

Cú pháp:

[<từ khóa>] Sub <tên thủ tục>([<các tham số>])



End Sub
Hoặc
[<từ khóa>] Function <tên hàm>([<các tham số>])

Return <giá trị>
End Function

Từ khóa có thể là một trong các giá trị ở bảng sau:

Các từ khóa khai báo phương thức

Tên Mô tả
Public Cho biết phương thức được gọi ở mọi nơi.
Protected Cho biết phương thức chỉ được gọi trong phạm vi của Class khai báo và các lớp

Học phần 3 – VB.NET Trang 64/187


Tài liệu hướng dẫn giảng dạy

Con (Subclass)
Friend Cho biết phương thức chỉ được gọi trong phạm vi của Project
Protected Friend Cho biết phương thức chỉ được gọi trong phạm vi Proctected và Friend
Private Cho biết phương thức chỉ được gọi trong phạm vi của Class
Overloads Cho biết phương thức nạp chồng một hay nhiều phương thức có cùng tên với
phương thức trong lớp cơ sở. Danh sách tham số trong phương thức này phải
khác với danh sách tham số của mỗi phương thức nạp chồng khác về số lượng,
hoặc về các kiểu dữ liệu hoặc cả hai.
Chúng ta không cần phải dùng từ khóa Overloads khi tạo các phương thức nạp
chồng trong một lớp. Nhưng nếu đã khai báo cho một thì phải khai báo cho tất
cả.
Không được phép sử dụng cả hai từ khóa Overloads và Shadows trong cùng
một phương thức.
Ví dụ chúng ta có các lớp Tinh và Toan như sau:
Public Class Tinh
Function BP(ByVal so As Short) As Integer
Return so ^ 2
End Function
Function BP(ByVal so As Integer) As Long
Return so ^ 2
End Function
End Class
Public Class Toan
Inherits Tinh
Overloads Function BP(ByVal so As Double) As Double
Return so ^ 2
End Function
End Class
Các hàm BP trong lớp Tinh có thể có hoặc không có từ OverLoads
Một thể hiện của lớp Toan có thể sử dụng tất cả các hàm Overloads
Overrides Cho biết phương thức ghi chồng một phương thức cùng tên của lớp cơ sở. Số
lượng tham số, kiểu dữ liệu của tham số cũng như kiểu giá trị trả về phải khớp
với của lớp cơ sở.
Overridable Cho biết phương thức này cho phép ghi chồng bằng một phương thức cùng tên
trong lớp Con. Phương thức với từ khóa Overrides mặc nhiên là được phép ghi
chồng.
NotOverridable Cho biết phương thức không được phép ghi chồng trong lớp Con.
MustOverride Cho biết phương thức không được cài đặt trong lớp khai báo nhưng phải cài
đặt trong lớp Con.
Shadows Cho biết phương thức che lấp một thành phần có tên tương tự, hoặc một tập
hợp các thành phần nạp chồng của lớp cơ sở. Tham số và giá trị trả về không
nhất thiết phải như trong thành phần bị che. Thành phần bị che không còn giá
trị trong lớp che nó.
Không được phép sử dụng cả hai từ khóa Overloads và Shadows trong cùng

Học phần 3 – VB.NET Trang 65/187


Tài liệu hướng dẫn giảng dạy

một phương thức.


Ví dụ: Chúng ta có lớp ClassCha với thuộc tính Cao:
Public Class ClassCha
Private h As Single
Property Cao() As Single
Get
Return h
End Get
Set(ByVal Value As Single)
h = Value
End Set
End Property
End Class
Và lớp ClassCon kế thừa từ lớp ClassCha và che mờ thuộc tính Cao bằng thủ
tục Cao như sau:
Public Class ClassCon
Inherits ClassCha
Public Shadows Sub Cao()
MessageBox.Show("Tôi sẽ còn cao hơn nữa", _
"Class Con")
End Sub
End Class

Shared Cho biết phương thức được dùng chung - nghĩa là phương thức này không liên
kết với một thể hiện nào của lớp. Chúng ta có thể gọi phương thức dùng chung
thông qua tên của lớp hoặc tên biến của một thể hiện cụ thể.
Ví dụ chúng ta có lớp TEST với một hàm Shared như sau:
Class TEST
Shared Function Cong(ByVal a As Integer, _
ByVal b As Integer) As Integer
Return a + b
End Function
End Class
Khi sử dụng, chúng ta có thể viết:
Dim y As TEST
Console.WriteLine(y.Cong(12, 9))
hoặc:
Console.WriteLine(TEST.Cong(12, 9))

Học phần 3 – VB.NET Trang 66/187


Tài liệu hướng dẫn giảng dạy

II.5. Khai báo thuộc tính (Property)


Thuộc tính là thành phần lưu giữ các tính chất, đặc điểm của đối tượng. Ứng với mỗi thuộc tính, chúng
ta cần khai báo một biến Private tương ứng để lưu giữ giá trị. Trong VB.NET, chúng ta dùng một cú
pháp chung cho truy xuất và gán trị của thuộc tính như sau:
Cú pháp:

' Khai báo biến lưu giữ giá trị của thuộc tính
Private mthuoctinh As <Kiểu dữ liệu>

[<Từ khoá>] Property Thuoc_tinh() As <Kiểu dữ liệu>


' Truy xuất giá trị của thuộc tính tức truy xuất đến giá trị của biến
Get
Return mthuoctinh
End Get
' Gán trị cho thuộc tính tức gán trị cho biến
Set (ByVal Value As <Kiểu dữ liệu>)
mthuoctinh = Value
End Set
End Property

Chúng ta có thể sử dụng các từ khai báo sau:

II.5.1. Default
Khai báo thuộc tính mặc định. Các thuộc tính này phải có tham số và có thể gán và truy xuất không
cần chỉ ra tên thuộc tính.
Một thuộc tính chỉ có thể là thuộc tính mặc định nếu thỏa các điều kiện:

– Mỗi Class chỉ được có một thuộc tính mặc định, phải kể đến cả các thuộc tính kế thừa.
– Thuộc tính mặc định không được là Shared hay Private
– Nếu một thuộc tính nạp chồng (Overloaded) là mặc định thì tất cả các thuộc tính cùng tên cũng
phải khai báo mặc định.
– Thuộc tính mặc định phải có ít nhất một tham số
Cú pháp:

Private mthuoctinh As <Kiểu dữ liệu>


Default Public Property Thuoc_tinh(Index as Integer) As <Kiểu dữ liệu>
Get
Return mthuoctinh
End Get
Set (ByVal Value As <Kiểu dữ liệu>)

mthuoctinh = Value
End Set

Học phần 3 – VB.NET Trang 67/187


Tài liệu hướng dẫn giảng dạy

End Property

II.5.2. ReadOnly
Cho biết thuộc tính chỉ được phép đọc không cho phép gán.
Cú pháp:

Private mthuoctinh As <Kiểu dữ liệu>


Public ReadOnly Property Thuoc_tinh() As <Kiểu dữ liệu>
Get
Return mthuoctinh
End Get
End Property

II.5.3. WriteOnly
Cho biết thuộc tính chỉ được phép gán không cho phép đọc.
Cú pháp:

Private mthuoctinh As <Kiểu dữ liệu>


Public WriteOnly Property Thuoctinh() As String
Set (ByVal Value As String)
mthuoctinh = Value
End Set
End Property

II.5.4. Overloads
Cho biết thuộc tính này nạp chồng một hoặc nhiều thuộc tính có cùng tên được định nghĩa trên lớp cơ
sở. Danh sách tham số trong thuộc tính này phải khác với danh sách tham số của mỗi thuộc tính nạp
chồng khác về số lượng, hoặc về các kiểu dữ liệu hoặc cả hai.
Chúng ta không cần phải dùng từ khóa Overloads khi tạo các thuộc tính nạp chồng trong một lớp.
Nhưng nếu đã khai báo cho một thì phải khai báo cho tất cả.
Không được phép sử dụng cả hai từ khóa sau một lượt: Overloads và Shadows trong cùng một thuộc
tính.

II.5.5. Overrides
Cho biết thuộc tính ghi chồng một thuộc tính cùng tên của lớp cơ sở. Số lượng tham số, kiểu dữ liệu
của tham số cũng như kiểu giá trị trả về phải khớp với của lớp cơ sở.

II.5.6. Overridable
Cho biết thuộc tính này được phép ghi chồng trong lớp Con.

II.5.7. NotOverridable
Cho biết thuộc tính không được phép ghi chồng trong lớp Con. Mặc nhiên, các thuộc tính là không
được phép ghi chồng.

Học phần 3 – VB.NET Trang 68/187


Tài liệu hướng dẫn giảng dạy

II.5.8. MustOverride
Cho biết thuộc tính không được cài đặt trong lớp và phải được cài đặt ở lớp Con.

II.5.9. Shadows
Cho biết thuộc tính che lấp một thuộc tính có tên tương tự, hoặc một tập hợp các thuộc tính Nạp chồng
của lớp cơ sở. Tham số và giá trị trả về không nhất thiết phải như trong thuộc tính bị che. Thuộc tính bị
che không còn giá trị trong lớp che nó.

II.5.10. Shared
Cho biết thuộc tính được chia sẻ - nghĩa là thuộc tính không gắn chặt với một thể hiện nào của lớp
nhưng được sử dụng chung giữa các thể hiện của một lớp.

II.6. Khai báo sự kiện (Event)


Sự kiện là thông điệp do một đối tượng phát sinh cho biết một hành động đang xảy ra. Hành động có
thể do sự tương tác của người dùng, do chương trình khác kích hoạt…Đối tượng kích hoạt biến cố được
gọi là đối tượng gửi biến cố. Đối tượng bắt sự kiện và đáp ứng lại gọi là đối tượng nhận sự kiện. Đối
tượng gửi không biết đối tượng nhận sự kiện do nó kích hoạt, nhưng giữa đối tượng gửi và đối tượng
nhận có một đối tượng trung gian. Trong .NET Framework có một kiểu đặc biệt thích hợp cho chức
năng của vai trò trung gian này là Delegate (ủy quyền).
Chức năng của sự kiện được xác định từ ba yếu tố liên quan: một đối tượng cung cấp dữ liệu sự kiện
(event data), một event delegate và một đối tượng kích hoạt sự kiện (sender). .NET Framework có một
qui ước về việc đặt tên các lớp và các phương thức liên quan đến sự kiện như sau:

II.6.1. Phát sinh sự kiện


Để một class phát sinh sự kiện EventName cần có các yếu tố sau:
– Một tham số sự kiện chứa các dữ liệu có tên EventNameEventArgs phát sinh từ lớp
System.EventArgs
– Một thành phần xử lý sự kiện có tên EventNameEventHandler. Đây là một thủ tục sẽ được gọi khi
sự kiện xảy ra. Chúng ta có thể sử dụng bất kỳ thủ tục hợp lệ nào làm thành phần xử lý sự kiện
nhưng không được là một hàm.
– Một đối tượng phát sinh sự kiện. Đối tượng này phải cung cấp :
ƒ Một khai báo sự kiện
[<Từ khoá>] Event EventName As EventNameEventHandler

ƒ Một phương thức tên OnEventName phát sinh sự kiện


ƒ Các đối tượng event delegate và đối tượng dữ liệu sự kiện (EventArgs) có thể phát sinh từ
những lớp tương ứng có sẵn trong .NET.
Các từ khoá khai báo sự kiện có thể là:

Các từ khóa khai báo sự kiện


Tên Mô tả
Public Sử dụng được ở mọi nơi. Sự kiện không có từ khóa mặc nhiên là Public.
Private Chỉ truy xuất trong phạm vi khai báo.
Protected Chỉ truy xuất trong phạm vi Class và SubClass.

Học phần 3 – VB.NET Trang 69/187


Tài liệu hướng dẫn giảng dạy

Friend Chỉ truy xuất trong phạm vi Project.


Protected Friend Chỉ truy xuất trong phạm vi của Protected và Friend
Shadows Cho biết sự kiện che mờ một thành phần có tên tương tự trong lớp cơ sở.
Chúng ta có thể che mờ một thành phần loại này bằng một thành phần loại
khác. Thành phần bị che mờ sẽ không còn tác dụng trong lớp kế thừa che mờ
nó.

Các sự kiện trong VB.NET không hỗ trợ đúng nguyên tắc kế thừa. Một sự kiện khai báo trong Class nào
chỉ được phép gọi phát sinh sự kiện (RaiseEvent) chỉ trong lớp đó mà thôi, không được gọi phát sinh kể
cả trong các lớp kế thừa.
Cú pháp để gọi phát sinh sự kiện như sau
Cú pháp:

RaiseEvent <tên sự kiện>()

Ví dụ chúng ta có lớp Con_Nguoi và thuộc tính Chieu_Cao, khi chiều cao thay đổi sẽ phát sinh sự kiện
Chieu_Cao_Thay_doi như sau
Ví dụ:

Public Class Con_Nguoi


Private Cao As Single
Public Event Chieu_Cao_Thay_doi()
Public Property Chieu_Cao() As Single
Get
Return Cao
End Get
Set(ByVal Value As Single)
Cao = Value
RaiseEvent Chieu_Cao_Thay_doi()
End Set
End Property
End Class

Để sử dụng các sự kiện trên một biến, chúng ta sử dụng cú pháp sau khi khai báo biến:

Private WithEvents <tên biến> As <tên Class>

II.6.2. Kết hợp sự kiện với xử lý sự kiện


Chúng ta kết hợp sự kiện với xử lý sự kiện bằng các lệnh: Handles hoặc AddHandler.

Từ khóa WithEvents và Handles cung cấp cách khai báo các xử lý sự kiện. Các sự kiện do một đối
tượng phát sinh với từ khóa WithEvents có thể được xử lý bằng bất kỳ thủ tục nào được chỉ ra trong
mệnh đề Handles của sự kiện. Tuy mệnh đề Handles là cách thức chuẩn để kết hợp một sự kiện với
một xử lý sự kiện, nhưng lại giới hạn số các biến cố kết hợp với cùng xử lý sự kiện khi biên dịch.
Các lệnh AddHandler và RemoveHandler uyển chuyển hơn trong việc kết hợp sự kiện với xử lý sự kiện.
Chúng cho phép chúng ta linh hoạt kết hợp và ngắt rời các sự kiện với các xử lý sự kiện lúc thực thi và

Học phần 3 – VB.NET Trang 70/187


Tài liệu hướng dẫn giảng dạy

chúng không đòi hỏi chúng ta phải khai báo biến với từ khóa WithEvents.
Với các sự kiện kết hợp với các form, control, Visual Basic .NET tự động phát sinh một xử lý sự kiện
rỗng và kết hợp với sự kiện.
Ví dụ khi chúng ta nhấp đúp vào một nút lệnh trên màn hình ở chế độ thiết kế, Visual Basic .NET tạo
một xử lý sự kiện kết hợp với sự kiện Click của nút lệnh như sau:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _


System.EventArgs) Handles Button1.Click
End Sub

Hoặc chúng ta kết hợp các biến cố Click của các nút lệnh Button1, Button2 cho cùng một xử lý sự kiện
như sau:

AddHandler Button1.Click, AddressOf Nhannut


AddHandler Button2.Click, AddressOf Nhannut

Private Sub Nhannut(ByVal sender As _
System.Object, ByVal e As System.EventArgs)

End Sub

II.7. Từ khóa Me, Mybase, MyClass


II.7.1. Me
Từ khóa Me được dùng khi chúng ta chỉ rõ muốn dùng các thành phần của chính thể hiện Class nơi viết
lệnh chứ không phải thành phần nào khác.

Ví dụ:

Public Class Con_nguoi


Private ten as String
Public Sub Lam_viec()
Dim ten as String
' biến cục bộ của Sub được sử dụng
ten = "Hùng"
' biến cấp Class được dùng
Me.ten = "Hùng"
End Sub
End Class

II.7.2. Mybase
Từ khóa Mybase được dùng trong Class kế thừa, khi chúng ta muốn dùng các phương thức của chính
Class cơ sở.

Ví dụ:
Lớp lopCha với thủ tục Gioi_thieu và tạo tiếp Class lopCon kế thừa từ lopCha

Học phần 3 – VB.NET Trang 71/187


Tài liệu hướng dẫn giảng dạy

Public Class lopCha


Public Overridable Sub Gioi_thieu()
MessageBox.Show(“Tôi là thể hiện của lopCha”)
End Sub
End Class
Public Class lopCon
Inherits lopCha
Public Overrides Sub Gioi_thieu()
MessageBox.Show("Tôi là thể hiện của lopCon")
Mybase.Gioi_thieu()
End Sub
End Class

Khi gọi phương thức Gioi_thieu của lopCon, chúng ta sẽ có hai thông báo: một của chính lopCon và
một của lopCha
Chú ý: Từ khóa Mybase
ƒ Chỉ được dùng để tham chiếu đến Class trung gian và các thành phần được kế thừa của nó.
ƒ Không phải là một đối tượng, nên thông thể gán trị, dùng làm tham số hoặc dùng trong toán tử
Is
ƒ Không được sử dụng trong các Standard Module.

II.7.3. MyClass
Từ khóa MyClass cho phép chúng ta gọi các phương thức Overridable của Class, dẫu các Class kế thừa
đã có các phương thức Overrides tương ứng.
Ví dụ:
Lớp lopCha với thủ tục Gioi_thieu và tạo tiếp Class lopCon kế thừa từ lopCha

Public Class lopCha


Public Sub Chao()
Gioithieu()
End Sub
Public Overridable Sub Gioi_thieu()
MessageBox.Show("Tôi là thể hiện của lopCha")
End Sub
End Class

Và một Class lopCon kế thừa từ lopCha có thủ tục Gioithieu ghi đè, và kế thừa thủ tục Chao của lopCha

Public Class lopCon


Inherits lopCha
Public Overrides Sub Gioi_thieu()
MessageBox.Show(“Tôi là thể hiện của lopCon”)
End Sub

Học phần 3 – VB.NET Trang 72/187


Tài liệu hướng dẫn giảng dạy

End Class

Với đoạn lệnh sau:

Dim a as New lopCon()


a.Chao() ‘ Tôi là thể hiện của lopCon

Nhưng nếu thủ tục Chao của lopCha như sau:

Public Sub Chao()


MyClass.Gioi_thieu()
End Sub

Thì :

a.Chao() ' Tôi là thể hiện của lopCha

II.8. Khởi tạo thể hiện


Để tạo đối tượng cho một Class, trình biên dịch gọi một hàm đặc biệt được gọi là bộ khởi tạo
(Constructor). Chúng ta có thể định nghĩa bộ khởi tạo trong Class. Nhưng nếu chúng ta không định
nghĩa, VB sẽ sử dụng bộ khởi tạo mặc định. Để định nghĩa bộ khởi tạo, chúng ta chỉ cần định nghĩa
một thủ tục New bên trong Class. Do tính chất nạp chồng (Overloading), nên Class có thể định nghĩa
nhiều bộ khởi tạo.

II.9. Abstract Base Class


II.9.1. Từ khoá MustInherit
Khi chúng ta muốn tạo một lớp chỉ dùng để thừa kế, phải khai báo với từ khóa MustInherit.
Lớp này không cho phép khởi tạo thể hiện, nhưng phải tạo lớp con kế thừa từ lớp này và khởi tạo thể
hiện từ lớp kế thừa:

Cú pháp:

Public MustInherit Class <tên lớp>

II.9.2. Từ khoá MustOverride


Tương tự với ý niệm MustInherit trong Class, ta cũng có từ khóa MustOverride cho một phương thức.
Trong lớp cơ sở ta khai báo một phương thức, nhưng yêu cầu phải được cài đặt trong lớp kế thừa, ta
sẽ khai báo phương thức đó như sau:
Cú pháp:

MustOverride Sub <tên thủ tục>

Thủ tục này không được có gì khác ngoài dòng khai báo. Thủ tục này được gọi là abstract method hay
pure virtual function, vì nó chỉ có phần khai báo không có phần định nghĩa. Trong các lớp kế thừa, các
thủ tục này buộc phải được cài đặt (Override) để sử dụng.
Kết hợp hai ý niệm MustInherit và MustOverride, chúng ta sẽ có Abstract Base Class. Đây là một Class
chỉ có khai báo không có phần cài đặt. Muốn dùng phải tạo class kế thừa, từ đó mới sử dụng được.
Ví dụ:

Học phần 3 – VB.NET Trang 73/187


Tài liệu hướng dẫn giảng dạy

Public MustInherit Class Con_nguoi


Public MustOverride Sub Chao()
Public MustOverride Sub Hoi_tham()
End Class

Lớp Abstract Base Class rất thích hợp để chúng ta tạo cái sườn hay bố cục của chương trình trong lúc
thiết kế. Tất cả những lớp kế thừa lớp Abstract Base Class đều phải cài đặt các thành phần đã khai báo
trong Abstract Base Class:
Ví dụ:

Public Class Nguoi_Viet


Inherits Con_nguoi
Public Override Sub Chao()

End Sub
Public Override Sub Hoi_tham()

End Sub
End Class

II.10. Giao tiếp (Interface)


Tương tự Abstract Base Class, Interface có thể khai báo tập hợp các thuộc tính, phương thức và sự
kiện, nhưng không có phần cài đặt chúng (Implementation). Các lớp tiếp nhận Interface đều phải cài
cặt các thành phần của Interface như đã khai báo.
Chúng ta có cú pháp sau để khai báo Interface:
Cú pháp:

[<Từ khóa>] Interface <tên gọi>


[ Inherits <tên interface1>[,<ten interface2>]]
[ [ Default ] Property <thuộc tính> ]
[ Function <tên hàm>]
[ Sub <tên thủ tục>]
[ Event <tên sự kiện>]
End Interface

Các từ khóa có thể là Public, Friend, Protected, Protected Friend hoặc Private

Ví dụ:

Public Interface IChaohoi


Sub Chao()
Sub Hoi_tham()
End Interface

Class nào tiếp nhận giao tiếp IChaohoi đều phải định nghĩa thủ tục Chao và Hoi_tham.

Học phần 3 – VB.NET Trang 74/187


Tài liệu hướng dẫn giảng dạy

Public Class Nguoi_Phap


Implements IChaohoi
Public Sub Chao() Implements IChaohoi.Chao
End Sub

Public Sub Hoi_tham() As String Implements IChaohoi.Hoi_tham


End Sub
End Class

Một số yếu tố sau đây giúp xác định sử dụng Abstract Base Class hay Interface:
ƒ Nếu Class tạo ra, sẽ được kế thừa nhiều tầng sau đó, thì Abstract Class là giải pháp thích hợp.
Vì trong trường hợp này, nếu nâng cấp lớp cơ sở (base class), toàn bộ các lớp kế thừa từ nó sẽ
được tự động nâng cấp theo. Ngược lại, Interface không cho phép thay đổi sau khi đã tạo ra.
Nếu có yêu cầu thay đổi, chúng ta buộc phải tạo Interface mới hoàn toàn.
ƒ Nếu muốn chức năng tạo ra sẽ áp dụng cho nhiều nhóm đối tượng (Class) khác nhau, Interface
là thích hợp. Abstract Class chỉ áp dụng được cho một nhóm đối tượng liên quan mật thiết
nhau, trong khi Interface là cách thức thích hợp nhất cho các Class không có gì liên quan nhau.
ƒ Để thiết kế một số ít chức năng nhỏ, ngắn gọn, sử dụng Interface. Nếu thiết kế một bộ các
chức năng lớn, sử dụng Abstract Class.
ƒ Nếu muốn cung cấp một số chức năng đã được cài đặt sẵn cho các đối tượng, sử dụng Abstract
Class, vì nó cho phép cài đặt sẵn trong Abstract Class trong khi Interface không cho phép cài
đặt sẵn trên bất kỳ thành phần nào của nó.

II.11. Lớp lồng ghép


Cài đặt lớp lồng ghép (có-một) là tạo và sử dụng các đối tượng trong một lớp nhưng không muốn cho
bên ngoài truy cập và sử dụng. Trở lại với ví dụ lớp Xe hơi có một Tay lái, nếu trong ứng dụng không
cần thiết phải có lớp Tay lái, chúng ta có thể xây dựng lớp Xe hơi có lồng ghép lớp Tay lái. Thông
thường, những trường hợp này lớp lồng ghép được khai báo là Private. Tuy nhiên các lớp lồng ghép
cũng khiến cho việc sử dụng và bảo trì thêm phần phức tạp. Dưới đây là một vài yếu tố giúp chúng ta
quyết định việc sử dụng lớp lồng ghép:
ƒ Nếu lớp đó không hề có ý nghĩa gì bên ngoài lớp chứa nó. Ví dụ Tay lái chỉ có ý nghĩa với Xe hơi
chứ không hề được quan tâm tại nơi nào khác trong ứng dụng.
ƒ Nếu các thành phần của lớp có nhu cầu truy xuất các thành phần khai báo Private của lớp chứa
nó.
Ví dụ:

Public Class Xehoi


Private tlai As New Taylai()
Enum Huonglai
trai = -1
phai = 1
thang = 0
End Enum
Private Class Taylai
Sub Retrai()

Học phần 3 – VB.NET Trang 75/187


Tài liệu hướng dẫn giảng dạy

MsgBox("Xe tu tu re trai")
End Sub
Sub Rephai()
MsgBox("Xe tu tu re phai")
End Sub
Sub Dithang()
MsgBox("Xe tiep tuc di thang")
End Sub
End Class
Sub Laixe(ByVal huong As Huonglai)
Select Case huong
Case Huonglai.trai
tlai.Retrai()
Case Huonglai.thang
tlai.Dithang()
Case Huonglai.phai
tlai.Rephai()
End Select
End Sub
End Class

II.12. Từ khóa Delegate


Từ khóa này được dùng để khai báo một thẻ ủy quyền. Đây là một đối tượng kiểu tham chiếu trỏ đến
một phương thức khác trong ứng dụng.
Cú pháp:

[ Public | Private | Protected | Friend | Protected Friend ] _


[ Shadows ] Delegate Sub <tên thủ tục>([<các tham số>])

hoặc

[ Public | Private | Protected | Friend | Protected Friend ] _


[ Shadows ] Delegate Function <tên hàm> ([<các tham số>]) As _
<kiểu dữ liệu>

Lệnh Delegate định nghĩa các kiểu tham số và kiểu giá trị trả về của một lớp ủy quyền. Bất kỳ phương
thức nào có kiểu các tham số và kiểu trị trả về phù hợp đều có thể là một thể hiện của lớp ủy quyền
đó. Thủ tục sẽ được gọi thực hiện bằng cách gọi phương thức Invoke của lớp ủy quyền.

Mỗi lớp ủy quyền định nghĩa một bộ khởi tạo có tham số là một phương thức. Cách truyền thủ tục như
một tham số cho phương thức theo cú pháp:
Cú pháp:

AddressOf <tên phương thức>

Ví dụ:

Học phần 3 – VB.NET Trang 76/187


Tài liệu hướng dẫn giảng dạy

Chúng ta có:
– Một khai báo ủy quyền
Delegate Function Lon_Hon(ByVal so1 as Integer, ByVal so2 as Integer) as
Integer

– Một hàm cài đặt như sau:


Function Lay_so_lon(ByVal so1 As Integer, ByVal so2 As Integer) As Integer
Return IIf(so1 > so2, so1, so2)
End Function

– Và hàm tìm số lớn nhất trong các số truyền vào như sau:
Function Lon_Nhat(ByRef Cacso() As Integer, ByVal sosanh As Lon_Hon) As
Integer
Dim i As Integer
Dim soMax As Integer = Cacso(0)
For i = 1 To Cacso.GetUpperBound(0)
soMax = sosanh(Cacso(i), soMax)
Next
Return soMax
End Function

Và đoạn lệnh khi sử dụng:

Dim a() As Integer = New Integer() {107, 15, 9, 20, 34, 6, 100, 99, 10}
Console.Write("Số lớn nhất trong mảng là:" (0), _
Lon_Nhat(a, AddressOf Lay_so_lon))

Học phần 3 – VB.NET Trang 77/187


Tài liệu hướng dẫn giảng dạy

Bài 4
TỔNG QUAN VỀ ADO.NET
Tóm tắt
Lý thuyết 1 tiết

Mục tiêu Các mục chính Bài tập

Bài học này sẽ cung cấp cho học viên 1. Tổng quan
các kiến thức cơ bản và giới thiệu các 2. Kiến trúc ADO.NET
đối tượng trong ADO.NET.
3. Các đặc điểm của ADO .Net
4. Content Component
5. Managed Provider Component

Học phần 3 – VB.NET Trang 78/187


Tài liệu hướng dẫn giảng dạy

I. Tổng quan
Hầu như bất kỳ ứng dụng nào cũng cần đến dữ liệu. Dữ liệu từ người dùng nhập vào, dữ liệu được lưu
trữ trong ứng dụng và dữ liệu từ các hệ thống khác,… tất cả đều là nguồn thông tin mà ứng dụng cần
xử lý với chức năng chính là hỗ trợ tìm kiếm, tính toán, thống kê và ra quyết định.

Để thực hiện các chức năng xử lý dữ liệu, người lập trình cần phải có các công cụ lập trình chuyên
dùng. Dữ liệu không đơn giản lưu trên các file văn bản hay file nhị phân với cấu trúc record do người
lập trình định nghĩa. Thay vào đó, hầu hết các ứng dụng tổ chức dữ liệu logic dựa trên cấu trúc cơ sở
dữ liệu quan hệ và lưu trữ vật lý dữ liệu dựa vào các hệ quản trị cơ sở dữ liệu quan hệ như Access, SQL
Server, Oracle, DB2,…
Khi dữ liệu trở thành trung tâm của ứng dụng thì việc cung cấp các chức năng tới người dùng phụ
thuộc vào khả năng xử lý và thao tác với dữ liệu. Vấn đề mà người thiết kế và xây dựng ứng dụng
quan tâm khi làm việc với dữ liệu là:
– Lưu trữ dữ liệu tập trung
– Đảm bảo toàn vẹn dữ liệu
– Đảm bảo khả năng truy xuất đồng thời của nhiều người dùng trên dữ liệu
– Đảm bảo thời gian hồi đáp ngắn cho mỗi người dùng
– Bảo mật dữ liệu
– Trao đổi dữ liệu giữa các hệ thống khác nhau
Những vấn đề này được giải quyết nhờ vào khả năng của các hệ quản trị cơ sở dữ liệu (HQT CSDL) và
cách phần mềm xử lý dữ liệu do hệ quản trị dữ liệu cung cấp. Với các database server sử dụng HQT
CSDL như Oracle, SQL Server,… dữ liệu được đảm bảo lưu trữ tập trung, toàn vẹn và truy xuất đồng
thời cũng như bảo mật. Tuy nhiên, thời gian hồi đáp người dùng và trao đổi dữ liệu phụ thuộc hoàn
toàn vào các phần mềm. Với các công cụ lập trình xử lý dữ liệu như ADO (Active Data Object),
Microsoft đem lại cho người lập trình một công cụ rất tự nhiên khi thực hiện các thao tác trên dữ liệu.
ADO được cải tiến liên tục trong các phiên bản hệ điều hành Windows hay MS Office. Tuy nhiên, với sự
ra đời của .NET, ADO không còn là thành phần Component độc lập nhưng gắn liền với .NET Framework
để cung cấp các dịch vụ xử lý dữ liệu.

ADO.NET có nhiều đổi mới so với ADO nhằm hướng tới người dùng nhiều hơn là người lập trình. Cấu
trúc mới của ADO.NET hơi gượng ép với người lập trình khi làm việc với dữ liệu nhưng lại nhằm cung
cấp khả năng truy xuất và xử lý dữ liệu lớn, đồng thời trên hệ thống ứng dụng phân tán nhiều người
dùng.
Đặc điểm chính của ADO.NET là làm việc với dữ liệu không kết nối. Dữ liệu được lưu trữ trong bộ nhớ
như một CSDL thu nhỏ gọi là DataSet, nhằm tăng tốc độ tính toán, xử lý tối đa và hạn chế việc sử
dụng tài nguyên trên Database Server. Đặc điểm quan trọng thứ hai là khả năng xử lý dữ liệu dạng
chuẩn XML. Dữ liệu ở dạng XML có thể trao đổi giữa bất kỳ hệ thống nào nên ứng dụng của bạn sẽ có
nhiều khả năng làm việc với nhiều ứng dụng khác.
Sau dây, chúng ta sẽ xem xét phần tổng quan kiến trúc của ADO.NET cùng với các kỹ thuật lập trình cơ
bản.

Học phần 3 – VB.NET Trang 79/187


Tài liệu hướng dẫn giảng dạy

II. Kiến trúc ADO .Net

Kiến trúc ADO.NET có thể chia làm 2 phần chính:

– Managed Provider Component: bao gồm các đối tượng như DataAdapter, DataReader,… giữ
nhiệm vụ làm việc trực tiếp với dữ liệu như database, file,…
– Content Component: bao gồm các đối tượng như DataSet, DataTable,… đại diện cho dữ liệu thực
sự cần làm việc. DataReader là đối tượng mới, giúp truy cập dữ liệu nhanh chóng nhưng forward-
only và read-only giống như ADO RecordSet sử dụng Server cursor, OpenFowardOnly và
LockReadOnly.
DataSet cũng là một đối tượng mới, không chỉ là dữ liệu, DataSet có thể coi là một bản sao gọn nhẹ
của CSDL trong bộ nhớ với nhiều bảng và các mối quan hệ.
DataAdapter là đối tượng kết nối giữa DataSet và CSDL, nó bao gồm 2 đối tượng Connection và
Command để cung cấp dữ liệu cho DataSet cũng như cập nhật dữ liệu từ DataSet xuống CSDL.
Trong ví dụ sau, chúng ta sẽ sử dụng điều khiển DataGrid để hiển thị dữ liệu từ bảng DMCV trong
C:\QL_NHAN_SU\CSDL\Qlns.mdb.

Ví dụ:

Chúng ta có:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As _


System.EventArgs) Handles MyBase.Load
Dim Ket_noi As New System.Data.OleDb.OleDbConnection("Provider= " & _

Học phần 3 – VB.NET Trang 80/187


Tài liệu hướng dẫn giảng dạy

"Microsoft.Jet.OLEDB.4.0; Data Source=" & Application.StartupPath _


& "\..\CSDL\Qlns.mdb")
Dim bo_doc_ghi As New System.Data.OleDb.OleDbDataAdapter _
("Select * From DMCV", Ket_noi)
Dim ds As New DataSet
Bo_doc_ghi.Fill(ds, "CONG_VIEC")
Luoi_cong_viec.DataSource = ds.Tables("CONG_VIEC")
End Sub

Với đoạn lệnh trên, chúng ta thấy cách lập trình của ADO.NET tương đối giống với ADODB thông
thường, đó là trước tiên cần kết nối với CSDL bằng một đối tượng Connection. Dữ liệu sẽ được quản lý
bởi một đối tượng, đó là DataSet như bạn thấy trong sơ đồ cấu trúc của ADO.NET.
Cũng trong sơ đồ này, bạn thấy rằng một DataAdapter có một Connection và nhiều đối tượng
Command. Trong ví dụ của chúng ta bạn thấy rõ điều này: bo_doc_ghi được tạo mới với một
connection là Ket_noi và một Select Command.

Đối tượng DataSet không làm việc trực tiếp với CSDL mà thông qua DataAdapter. Do đó, để DataSet có
dữ liệu, bạn phải dùng phương thức Fill của bo_doc_ghi lấy dữ liệu từ Qlns.mdb thông qua connection
Ket_noi đổ vào một bảng trong DataSet ds. Cuối cùng, để hiển thị dữ liệu chúng ta thực hiện việc liên
kết điều khiển với nguồn dữ liệu (Binding): kết nối Luoi_cong_viec với bảng "CONG_VIEC" trong ds.

III. Các đặc điểm của ADO.Net


ADO.NET có nhiều thay đổi so với ADO trước đây dù vẫn giữ lại kiến trúc các đối tượng độc lập với
nhau và cố gắng không thay đổi cách thức các lập trình viên đã sử dụng quen thuộc với ADO. ADO.NET
có nhiều đặc điểm mới, nổi bật:
– Interoperability
– Scalability
– Productivity
– Performance

III.1. Interoperability – Tương tác giữa nhiều hệ thống khác nhau


Trong các hệ thống phân tán, dữ liệu được chuyển ở dạng disconnected recordset giữa Data provider
và Data consumer. Vì ở dạng RecordSet, cả provider và consumer cần phải sử dụng COM để trao đổi
dữ liệu dẫn đến việc khó mở rộng hệ thống vì COM không làm việc qua Firewall và Network Address
Translator (NAT).
ADO.NET giải quyết vấn đề này bằng cách thay đổi về bản chất của việc đóng gói dữ liệu trước khi
truyền trên mạng:

ƒ Với ADO, Disconnected RecordSet được đóng gói ở dạng Network Data Representation (NDR)
trước khi truyền trên mạng. NDR vẫn là dạng đối tượng mà ở tầng Application, data provider và
data consumer phải sử dụng kỹ thuật COM để xử lý.
ƒ ADO.NET thay thế NDR bằng định dạng mới: XML. Với bản chất Text, XML hoàn toàn có thể sử
dụng HTTP để trao đổi dữ liệu. Hơn nữa XML document dễ dàng được xử lý mà không cần đến
kỹ thuật COM. XML là chuẩn để trao đổi dữ liệu mới nhất và đang được hỗ trợ rất rộng rãi.

Học phần 3 – VB.NET Trang 81/187


Tài liệu hướng dẫn giảng dạy

III.2. Scalability - Hỗ trợ nhiều người dùng


ADO làm việc trên mô hình Client/Server, Client sẽ kết nối liên tục với Server trong suốt quá trình làm
việc. Điều này làm cho Server trở nên Nạp chồng khi có quá nhiều Client kết nối.

ADO.NET sử dụng dữ liệu ở dạng disconnected data:


ƒ Client tạo kết nối với Server để lấy dữ liệu
ƒ Server gửi dữ liệu về cho Client
ƒ Client ngắt kết nối với Server
ƒ Khi cần cập nhật dữ liệu, kết nối giữa Client và Server được phục hồi
Với cơ chế disconnected data, thời gian kết nối giữa Client và Server không còn lâu dài như trước,
Server có khả năng phục vụ nhiều Client hơn hẳn so với cơ chế của ADO trước đây.

Cơ chế disconnected data có hai điểm đáng chú ý:


ƒ Dữ liệu sẽ không phản ánh kịp thời những thay đổi dữ liệu trong một hệ thống Client/Server với
nhiều người dùng?
Trên thực tế, người dùng khi làm việc với các hệ thống phân tán hiểu và chấp nhận dữ liệu có
một độ trễ và sai lệch nhỏ, không đáng kể (tương tự như các ứng dụng Web).
ADO trước đây nếu sử dụng RecordSet ở dạng OpenStatic thì cũng không tốt hơn cơ chế
disconnected data là bao.
ƒ Thời gian cho một lần tạo kết nối giữa Client và Server là khá lớn, việc ngắt kết nối sau đó tạo
lại kết nối để cập nhật dữ liệu sẽ chậm?
Vấn đề này được ADO.NET giải quyết khá đơn giản bằng cơ chế connection pooling, thông tin
về mối kết nối vẫn còn được lưu giữ ở Server trong khoảng thời gian nhất định và khi Server
còn đủ tài nguyên, mỗi khi Client cần kết nối lại với Server, thông tin kết nối được lấy ra từ
connection pool nên tốc độ không bị ảnh hưởng.

III.3. Productivity - Mở rộng khả năng làm việc với CSDL


ADO.NET vẫn giữ nguyên hướng tiếp cận cũ của ADO nên người lập trình sẽ không mất nhiều thời gian
để học cách sử dụng. ADO.NET vẫn giữ kiến trúc các đối tượng độc lập và về mặt ý nghĩa nói chung,
các đối tượng trong ADO.NET và ADO cũng gần giống nhau, vẫn có Connection, Command và đối
tượng đại diện cho dữ liệu cần xử lý. Điểm mạnh hơn của ADO.NET là DataSet tích hợp vào trong nó
nhiều chức năng hơn hẳn những gì mà RecordSet làm được.

Với ADO.NET, có sự tập trung rõ ràng hơn về các chức năng của các đối tượng. Ví dụ, Connection
không còn lo việc thi hành một câu lệnh SQL hay một Stored Procedure nữa, công việc này được giao
hoàn toàn cho Command đảm nhận.

Đáng chú ý hơn, ADO.NET phát triển trên .NET là component có thể kế thừa được. Người lập trình
hoàn toàn có khả năng kế thừa các đối tượng của ADO.NET để xây dựng các đối tượng mới tốt hơn và
phù hợp với nhu cầu phát triển ứng dụng của mình.
Cuối cùng, Visual Studio .NET với Component Designer giúp người lập trình tạo ra các DataSet nhanh
chóng với nội dung lệnh rõ ràng hơn những gì Data Form Wizard của Visual Studio 6 trước đây tạo ra.

III.4. Performance - Hiệu quả cao trong xử lý dữ liệu


Với các thay đổi trong bản chất cơ chế thực hiện, hiệu quả của ứng dụng dùng ADO.NET sẽ cao hơn
nhiều.

Học phần 3 – VB.NET Trang 82/187


Tài liệu hướng dẫn giảng dạy

ƒ Disconnected data đảm bảo ứng dụng trên Client ít gặp lỗi khi xử lý dữ liệu đồng thời giúp mở
rộng ứng dụng tới nhiều người dùng hơn. Các managed provider component hỗ trợ tính năng
thiết lập connection pooling ngầm định để giảm bớt thời gian tái kết nối.
ƒ Định dạng XML thay thế cho NDR trong trao đổi dữ liệu giữa Server và Client giúp cho dữ liệu
có thể được xử lý bởi nhiều client hơn dù ứng dụng trên Client có hay không sử dụng COM. XML
cũng giúp việc truyền thông nhanh hơn vì không cần đóng gói phức tạp như NDR hay chuyển
qua chuyển lại giữa dữ liệu thô sang dữ liệu ở dạng đối tượng.

IV. Content Component


Content component là các đối tượng đại diện cho dữ liệu cần xử lý. Trong ADO, RecordSet là content
component. Dữ liệu trong RecordSet ở dạng bảng, bao gồm các Row và Column. Trong ADO.NET, dữ
liệu được đại diện bởi DataSet nhưng dưới hình ảnh của một CSDL thu gọn, có nhiều table và các mối
quan hệ. Các class chính giúp tạo nên content component bao gồm:
– DataSet
– DataTable
– DataView
– DataRow
– DataColumn
– DataRelation.
DataSet

DataTableCollection

DataTable

DataRowCollection

«DataRow

DataColumnCollection

DataColumn

DataView

DataRelationCollection

DataRelation

Content Component

IV.1. DataSet
Với ADO, dữ liệu chứa trong RecordSet cho dù chúng được lấy từ một hay nhiều bảng. Vì ADO không
có cách nào mô tả mối quan hệ giữa các bảng trong CSDL với nhau, cách duy nhất để lấy dữ liệu từ
nhiều bảng là viết các câu truy vấn SQL kết giữa các bảng với nhau.

ADO.NET chứa dữ liệu trong DataSet cùng với mối quan hệ giữa các dữ liệu đó. DataSet giống như một
hình ảnh về CSDL trong bộ nhớ, có thể có nhiều DataTable và các mối quan hệ giữa chúng đại diện bởi

Học phần 3 – VB.NET Trang 83/187


Tài liệu hướng dẫn giảng dạy

các DataRelation.
Vì DataSet dùng cơ chế disconnected data, cần có chức năng giúp kiểm soát các thay đổi về dữ liệu đã
xảy ra và cập nhật những thay đổi đó xuống CSDL. Các chức năng được thực hiện qua các phương
thức:

ƒ HasChanges()
ƒ HasErrors()
ƒ GetChanges()
ƒ AcceptChanges()
ƒ RejectChanges()
Người lập trình có thể sử dụng các phương thức (hoặc hàm) này để kiểm tra sự thay đổi trên DataSet,
tập hợp những thay đổi đó vào một DataSet khác, tìm các lỗi và sau đó chấp nhận cập nhật hay bỏ qua
những thay đổi.

Sơ đồ đối tượng trên đây minh hoạ các đối tượng trong tập hợp Content Component và sự liên quan
giữa các đối tượng đó.

IV.2. DataTable
Là một thành phần trong DataSet, DataTable chứa dữ liệu của một bảng trong DataSet và thuộc lớp
DataTable. DataTable bao gồm:
ƒ Tập hợp Columns thuộc lớp DataColumnCollection trong đó mỗi cột là một đối tượng thuộc lớp
DataColumn
ƒ Tập hợp Rows thuộc lớp DataRowCollection trong đó mỗi dòng là một đối tượng thuộc lớp
DataRow.

IV.3. DataRelation
DataSet bao gồm tập hợp các table đại diện bởi các đối tượng DataTable và quan hệ giữa các table đó
đại diện bởi các đối tượng DataRelation.
Với DataRelation, người lập trình có thể:
ƒ Định nghĩa được mối quan hệ giữa các bảng
ƒ Duyệt dữ liệu trong các bảng theo kiểu Master – Detail
Một đối tượng kiểu DataRelation bao gồm các thông tin:

ƒ Tên của Parent table và Child table


ƒ Các column trong DataRelation đại diện cho Primary key trong Parent và Foreign key trong Child
table
Với DataRelation, ADO.NET cung cấp cho người lập trình một cách thức mới để xử lý dữ liệu. Dữ liệu
vẫn nằm trong các bảng thay vì bị gom từ nhiều bảng thành một RecordSet nhưng vẫn có thể truy cập
dễ dàng và hiệu quả hơn.

IV.4. Ràng buộc trên quan hệ


ADO.NET chỉ cho phép xác định hai loại ràng buộc:
ƒ UniqueConstraint: đảm bảo tính duy nhất về giá trị của một cột trong table

Học phần 3 – VB.NET Trang 84/187


Tài liệu hướng dẫn giảng dạy

ƒ ForeignKeyConstraint: chỉ ra cách ứng dụng sẽ thực hiện khi cập nhật hay xoá dữ liệu trên bảng
có quan hệ với bảng khác. Các giá trị của ForeignKeyConstraint:
+ None: không làm gì cả
+ Cascade: phụ thuộc vào dòng trên parent table sẽ bị cập nhật hay xoá
+ SetDefault: giá trị của cột khoá ngoại trên detail table được đặt về giá trị mặc định khi dòng
trên parent table bị xoá
+ SetNull: Giống SetDefault, giá trị được đặt là Null

IV.5. DataView
DataView gần giống với khái niệm RecordSet của ADO. Trên một DataTable có thể tạo nhiều DataView
với các điều kiện lọc, sắp xếp dữ liệu khác nhau. Trên DataView ta có thể xem hay thay đổi giá trị các
mẩu tin.
DataView của ADO.NET còn giữ nhiệm vụ kết nối với các control của Window Form và Web Form.

V. Managed Provider Component


Microsoft cung cấp hai bộ provider component trong phiên bản ADO.NET này là OLEDB và SQL. OLEDB
managed provider bao gồm các đối tượng:
– OleDBConnection
– OleDBCommand
– OleDBParemeter
– OleDBDataReader
– OleDBDataAdapter
Tương tự với OLEDB nhưng để tăng hiệu quả cho ứng dụng sử dụng Database trên SQL Server, SQL
managed provider cũng có các đối tượng giống của OLEDB nhưng bắt đấu với tên SQL thay cho
OLEDB.
Hình dưới đây cho thấy các đối tượng tương ứng trong OLEDB và SQL Provider implement hoặc kế
thừa từ interface hay class nào.

IDBConnection IDBCommand

OleDBConnection SQLConnection OleDBCommand SQLCommand

IDBParameterCollection

OleDBParameterCollection SQLParameterCollection

IDataReader DataAdapter

OleDBDataReader SQLDataReader OleDBDataAdapter SQLDataAdapter

Học phần 3 – VB.NET Trang 85/187


Tài liệu hướng dẫn giảng dạy

V.1. Connection
Cả OleDBConnection và SQLConnection đều có các thuộc tính và phương thức giống nhau như
ConnectionString, State hay Open.
Nói chung Connection của ADO.NET và ADO đều có cách sử dụng tương tự nhau ngoại trừ:
ƒ Connection của ADO.NET không thể thực hiện các câu truy vấn hay các stored procedure vì
không còn phương thức Execute nữa.
ƒ Connection của ADO.NET không còn hỗ trợ Transaction. Với ADO.NET, một transaction được
quản lý bởi đối tượng OleDBTransaction hoặc SQLTransaction (cả hai đều implement
IdbTransaction). Đối tượng Transaction hỗ trợ các phương thức như Commit và Rollbacks.
SQLTransaction còn hỗ trợ các checkpoint trong quá trình rollback.
Các provider mà OLEDB và SQL có thể dùng để kết nối dữ liệu là:
ƒ SQLOLEDB: OLEDB Provider của Microsoft cho SQL Server
ƒ MSDAORA: OLEDB provider của Microsoft cho Oracle
ƒ JOLT: OLEDB provider cho Jet.

V.2. Command
Đối tượng Command vẫn có cùng cách sử dụng như Command của ADO. Thuộc tính Connection của
SQLCommand hoặc OleDBCommand chỉ ra kết nối với CSDL sẽ sử dụng. Command cũng có thể sử
dụng các tham số để thi hành các stored procedure.
Sơ đồ ở hình trên cho thấy mối liên hệ giữa Command với Connection và DataReader. Command trong
ADO.NET có các cách thức thực hiện lệnh là:
ƒ ExecuteReader(): dùng đề thực hiện các câu truy vấn trả về dữ liệu. Dữ liệu trả về sẽ là một đối
tượng DataReader hoặc một đối tượng nào đó có implement IdbReader interface.
ƒ ExecuteNonQuery(): dùng để thực hiện các lệnh cập nhật dữ liệu.
ƒ ExecuteScalar(): dùng để thực hiện các lệnh tính toán và trả về một dòng, một cột chứa kết quả
của lệnh tính toán.

V.3. DataReader
DataReader thực sự là một đối tượng tương tự với RecordSet của ADO ngoại trừ khả năng giới hạn của
nó là ReadOnly lock và ForwardOnly cursor. Một DataReader được tạo ra bằng cách thực hiện phương
thức ExecuteReader của đối tượng Command.
DataReader hỗ trợ về mặt tốc độ khi truy cập dữ liệu, tuy nhiên nó sử dụng cursor ở phía Server và kết
nối với Server trong suốt quá trình đọc dữ liệu. Việc này khác với cơ chế sử dụng Disconnect data của
ADO.NET và giảm khả năng mở rộng của ứng dụng. Vì vậy khi đã có một đối tượng DataReader, cần
phải tiến hành việc đọc dữ liệu càng nhanh càng tốt.
Sử dụng Connection kết hợp với Command và DataReader là một cách được coi là "low level" của
ADO.NET để thao tác với dữ liệu. ADO.NET cung cấp DataAdapter là một kết hợp của Connection với
các Command giúp kết nối DataSet với database trên Server.

V.4. DataAdapter
DataAdapter được ADO.NET cung cấp như một công cụ giúp kết nối dữ liệu của một table trong

Học phần 3 – VB.NET Trang 86/187


Tài liệu hướng dẫn giảng dạy

DataSet với database trên Server.


IDataAdapter DataAdapter

DbDataAdapter

OleDBDataAdapter SQLDataAdapter

DataAdapter
Hình trên mô tả mô hình phân cấp các class của DataAdapter, cả SQLDataAdapter và
OleDBDataAdapter đều thừa kế từ class DbDataAdapter, DbDataAdapter lại thừa kết từ abstract class
DataAdapter, đến lượt abstract class này lại implement IDataAdapter interface để hỗ trợ hai phương
thức Fill và Update.
ƒ Để lấy dữ liệu cho một table trong DataSet, sử dụng phương thức Fill(), để cập nhật dữ liệu cho
DataSet, sử dụng phương thức Update().
ƒ Để lấy dữ liệu, DataAdapter dùng SELECT query thông qua thuộc tính SelectCommand. Để cập
nhật dữ liệu, DataAdapter dùng các câu query UPDATE, INSERT, DETETE thông qua các thuộc
tính UpdateCommand, InsertCommand và DeleteCommand.
Ngoài Fill và Update, DataAdapter còn kế thừa thuộc tính TableMappings giúp cung cấp cho người dùng
các tên table và tên column dễ đọc hơn các tên thực được sử dụng trong Database.
Trong các đối tượng Command của DataAdapter, chỉ có đối SelectCommand là bắt buộc, các đối tượng
còn lại đều có thể tự động được phát sinh.
Hình dưới đây mô tả quan hệ giữa các đối tượng thuộc Managed Provider Components.

Command Exception

Connection ErrorCollection
ParameterCollection Error
Parameter
DataReader
DataAdapter
SelectCommand
InsertCommand
DeleteCommand
UpdateCommand
DataTableMappingCollection

DataTableMappingCollection
DataColumnMappingCollection
DataColumnMapping

Học phần 3 – VB.NET Trang 87/187


Tài liệu hướng dẫn giảng dạy

Bài 5
CONNECTION, COMMAND,
DATAADAPTER
Tóm tắt
Lý thuyết 2 tiết - Thực hành 5 tiết

Mục tiêu Các mục chính Bài tập

Kết thúc bài học này, học viên có thể 1. Connection 3.1, 3.2
làm việc với dữ liệu thông qua các đối 2. Command
tượng ADO.NET
3. DataAdapter

Học phần 3 – VB.NET Trang 88/187


Tài liệu hướng dẫn giảng dạy

I. Connection
Vai trò của Connection trong ADO.NET cũng như trong ADO là tạo kết nối giữa ứng dụng và nguồn dữ
liệu. Điểm khác biệt chính là ADO.NET không còn hổ trợ các thao tác dữ liệu có kết nối. Mặt khác,
Connection trong ADO.NET giờ đây chỉ đóng vai trò tạo kênh thông tin giữa ứng dụng và CSDL, không
thực hiện các lệnh truy xuất, cập nhật CSDL như trong ADO.

Connection
CSDL

I.1. Data Provider


Các Data Provider có sẵn trong ADO.NET là:
ƒ SysTem.Data.OleDb
ƒ SysTem.Data.SqlClient
Ứng với mỗi không gian tên, chúng ta có một Connection tương ứng:
ƒ SysTem.Data.OleDb.OleDbConnection
ƒ SysTem.Data.SqlClient.SqlConnection
Chúng ta có thể sử dụng SysTem.Data.OleDb.OleDbConnection cho mọi nguồn dữ liệu. Nhưng để tận
dụng các đặc điểm của những Data Provider khác nhau, chúng ta có thể chỉ rõ Data Provider muốn sử
dụng. Ngoài SQL Server Provider, ADO.NET cũng hỗ trợ một số Data Provider khác như:
ƒ SysTem.Data.OracleClient qua tập tin System.Data.OracleClient.dll cho Oracle.
ƒ Microsoft.Data.Odbc qua tập tin Microsoft.Data.Odbc.dll cho ODBC
ƒ Microsoft.Data.SqlXml qua tập tin Microsoft.Data.SqlXml.dll cho Xml trên SQL Server
Với những Data Provider không cung cấp sẵn, khi sử dụng, chúng ta cần tham chiếu theo cách sau
Project - Add Reference - <Data Provider>
Ví dụ:

Imports SysTem.Data.OleDb

Dim ket_noi As New OleDbConnection()

I.2. ConnectionString
Trước khi thực hiện kết nối, cần khai báo các thông tin cần thiết cho Connection thông qua thuộc tính
ConnectionString. Cách khai báo thay đổi tùy thuộc Data Provider. Với OLEDB Provider có thể gồm các
thành phần
ƒ Provider: Khai báo Data Provider

Học phần 3 – VB.NET Trang 89/187


Tài liệu hướng dẫn giảng dạy

ƒ Data Source: Nguồn dữ liệu


ƒ User ID: Tên người dùng
ƒ Password: Mật khẩu
Ví dụ: Tạo Connection đến CSDL Access sử dụng OLeDbConnection

Imports SysTem.Data.OleDb
Dim chuoi_kn As String = "Provider=Microsoft.Jet.OLEDB.4.0; " & _
"Data Source =" & <đường dẫn>
Dim cnn As New OleDbConnection(chuoi_kn)

Ví dụ: Tạo Connection đến CSDL SQL Server sử dụng OLeDbConnection

Imports SysTem.Data.OleDb
Dim chuoi_kn As String = "Provider=SQLOLED;User ID=" & <người dùng> & _
";Password =" & <mật khẩu> & ";Data Source=" & <tên hoặc TCP/IP server> _
& ";Initial Catalog =" & <tên Database>
Dim cnn As New OleDbConnection(chuoi_kn)

Ví dụ: Tạo Connection đến CSDL Oracle sử dụng OLeDbConnection

Imports SysTem.Data.OleDb
Dim chuoi_kn As String = "Provider=MSDAORA.1;User ID=" & <người dùng> & _
";Password =" & <mật khẩu> & ";Data Source=" & <đường dẫn>
Dim cnn As New OleDbConnection(chuoi_kn)

SqlConnection chỉ cho phép kết nối đến dữ liệu SQL Server từ phiên bản 7.0 trở về sau. Cách khai báo
khác hơn với các thành phần chính như sau:

ƒ Data Source: Tên máy nơi cài đặt SQL Server có nguồn dữ liệu muốn kết nối
ƒ Initial Catalog: Tên database muốn kết nối
ƒ Integrated Security : True(SSPI)/ False chỉ định dùng cơ chế bảo mật của Windows Login (True)
hay cơ chế bảo mật của SQL Server (False)
ƒ User ID: Tên người dùng (phải khai báo khi Integrated Security = False)
ƒ PassWord: Mật khẩu (phải khai báo khi Integrated Security = False)
Việc sử dụng cơ chế bảo mật nào tùy thuộc SQL Server qui định.
Ví dụ: Tạo Connection đến CSDL SQL Server sử dụng SqlConnection

Imports SysTem.Data.SqlClient
Dim chuoi_kn As String = "Data Source=" & <địa chỉ TCP/IP hay tên máy> & _
"Initial Catalog=" & <tên database> & _
";User ID =" & <tên người dùng> & ";Password =" & <mật khẩu>
Dim cnn As New SqlConnection(chuoi_kn)

Hoặc

Imports SysTem.Data.SqlClient
Dim chuoi_kn As String = "Data Source=" & <địa chỉ TCP/IP hay tên máy> & _
"Initial Catalog=" & <tên database> & ";Integrated Security =SSPI"

Học phần 3 – VB.NET Trang 90/187


Tài liệu hướng dẫn giảng dạy

Dim cnn As New SqlConnection(chuoi_kn)

I.3. Các thuộc tính khác của Connection


Các thuộc tính
Tên Mô tả
Database (Chỉ đọc) Tương ứng với Initial Catalog (SQL) hay tên database muốn làm việc
(OLEDB)
DataSource (Chỉ đọc) Tương ứng với Data Source (OLEDB và SQL)
Provider (Chỉ đọc) Tương ứng với Provider (OLEDB)
State Tình trạng kết nối của Connection với các giá trị:
ƒ Broken: Kết nối với nguồn dữ liệu đã bị ngắt. Tình trạng này chỉ xảy ra
sau khi đã kết nối.
ƒ Closed: Kết nối đã đóng.
ƒ Connecting: Đang kết nối với nguồn dữ liệu.
ƒ Executing: Kết nối đang thực hiện một lệnh.
ƒ Fetching: Kết nối đang truy xuất dữ liệu.
ƒ Open: Kết nối đang mở.

I.4. Các phương thức trên Connection


Các phương thức
Tên Mô tả
BeginTransaction Bắt đầu một giao tác dữ liệu và trả về một đối tượng OleDbTransaction hoặc
SQLTransaction tương ứng
ChangeDatabase Thay đổi database làm việc.
ChangeDatabase(<tên database>)
Close Đóng kết nối với nguồn dữ liệu. Sử dụng phương thức này để đóng Connection
đang mở.
CreateCommand Tạo và trả về một Command dựa vào Connection hiện hành.
CreateCommand()
Dispose Xoá mọi tài nguyên liên quan đến Connection trên vùng nhớ
Open Thực hiện kết nối với các thông tin đã khai báo trong ConnectionString

I.5. Minh họa tạo Connection


Sau đây là một ví dụ tạo Connection kết nối với tập tin CSDL Access C:\QlHanghoa.mdb bằng lệnh và
bằng điều khiển OledbConnection.
Ví dụ:

Imports System.Data.Oledb

Dim chuoi_kn As String = "Provider =Microsoft.Jet.OLEDB.4.0; " & _

Học phần 3 – VB.NET Trang 91/187


Tài liệu hướng dẫn giảng dạy

"Data Source =C:\QlHanghoa.mdb"


Dim cnn As New OleDbConnection(chuoi_kn)
cnn.Open()

' các lệnh
cnn.Close()

II. Command
Sau khi tạo kết nối với nguồn dữ liệu, mọi thao tác trên nguồn dữ liệu đó đều được thực hiện thông
qua Command. Tùy theo loại Connection, đối tượng Command thuộc không gian tên như sau:
– System.Data.OleDb.OleDbCommand
– System.Data.SqlClient.SqlCommand

II.1. Tạo Command


Chúng ta có thể tạo đối tượng Command qua các cách sau thông qua một đối tượng Connection:
Cú pháp:

Dim <biến Command> As New <loại>Command()


<biến Command>.Connection = <biến Connection>
<biến Command>.CommandText = <lệnh>

Hoặc

Dim <biến Command> As New <loại>Command(<lệnh>)


<biến Command>.Connection = <biến Connection>

Hoặc

Dim <biến Command> As _


New <loại>Command(<lệnh SQL>, <biến Connection>)

Hoặc

Dim <biến Command> As <loại>Command = <biến Connection>.CreateCommand()


<biến Command>.CommandText = <lệnh>

II.2. Các thuộc tính của Command


Các thuộc tính
Tên Mô tả
CommandText Lệnh SQL,tên bảng hoặc tên stored procedure muốn thực hiện trên nguồn dữ
liệu. (đọc ghi)
CommandType Giá trị cho biết nội dung CommandText là gì với các giá trị sau:
ƒ Text: (mặc định) một câu lệnh SQL
ƒ Storedprocedure: tên một thủ tục nội
ƒ TableDirect: tên của bảng. Khi CommandType có giá trị nầy,

Học phần 3 – VB.NET Trang 92/187


Tài liệu hướng dẫn giảng dạy

CommandText là tên của một bảng. Khi Command thực hiện sẽ trả về
đủ các dòng và các cột (chỉ dùng cho OledbCommand)
Ví dụ:
Imports Systm.Data.Oledb

Dim chuoi As String ="Provider=SQLOLEDB; " & _
"Integrated Security = SSPI; " & _
"Initial Catalog=DAT_GIAO;Data Source=HUUTHIEN"
Dim cnn As New OleDbConnection(chuoi)
cnn.Open()
Dim lenh As New OleDbCommand("PHIEU_NHAP",cnn)
lenh.CommandType = CommandType.TableDirect

Connection Đối tượng Connection sử dụng cho Command


Parameters Tập hợp các tham số dùng trong Command (xem phần Parameter)
Transaction Giao tác mà trên đó Command đang thực hiện

II.3. Parameter
Lệnh SQL trong CommandText có thể sử dụng các dấu hỏi (?) thay thế cho trị chưa xác định và khi
thực hiện sẽ dùng đối tượng Parameter để truyền giá trị vào chỗ các dấu hỏi. Tùy theo Command,
Parameter sẽ khai báo từ lớp OledbParameter hay SqlParameter.
Cú pháp:

Dim <tên parameter> As New OledbParameter|SqlParameter()


Dim <tên parameter> As New OledbParameter|SqlParameter(<tên>)
Dim <tên parameter> As New OledbParameter|SqlParameter(<tên>, <giá trị>)

II.3.1. Các thuộc tính của Parameter


Các thuộc tính
Tên Mô tả
Direction Giá trị cho biết loại tham số với các giá trị sau: (đọc ghi)
ƒ Input (mặc định): loại tham số đầu vào
ƒ InputOutput: loại tham số vào và ra
ƒ Output: loại tham số đầu ra
ƒ ReturnValue: loại tham số nhận giá trị trả về của một thủ tục nội, một
hàm, hay một hàm do người dùng định nghĩa.

OleDbType Kiểu dữ liệu OleDb hoặc SqlDb của tham số. (đọc ghi)
SqlDbType
ParameterName Tên tham số. (đọc ghi)
Value Giá trị của tham số. (đọc ghi)

Học phần 3 – VB.NET Trang 93/187


Tài liệu hướng dẫn giảng dạy

Để đưa một tham số cho Command, chúng ta có thể sử dụng một trong các cách sau:

II.3.2. Tạo Parameter với CreateParameter của Command


Ví dụ: Khi sử dụng OleDbCommand

lenh.CommandText = "Select * from CTNHAP where sopn = ?"


Dim thamso As OleDbParameter = lenh.CreateParameter()
thamso.Value = "PN01"
lenh.Parameters.Add(thamso)

Ví dụ: Khi sử dụng SqlCommand

lenh.CommandText = "Select * from CTNHAP where sopn = @sp"


Dim thamso As SqlParameter = lenh.CreateParameter()
thamso.ParameterName = "@sp"
thamso.Value = "PN01"
lenh.Parameters.Add(thamso)

II.3.3. Đưa tham số trực tiếp vào tập hợp Parameters


Ví dụ: Khi sử dụng OleDbCommand

lenh.CommandText = "Select * from CTNHAP where sopn = ? and mavtu = ?"


‘ thứ tự đưa tham số vào phải theo thứ tự trong lệnh SQL
Dim ts1 As OleDbParameter = lenh.Parameters.Add("phieu", _
OleDbType.Char, 4)
ts1.Value = "PN01"
Dim ts2 As OleDbParameter = lenh.Parameters.Add("vattu", _
OleDbType.Char, 4)
ts1.Value = "S001"

Ví dụ: Khi sử dụng SqlCommand

lenh.CommandText = "Select * from CTNHAP where sopn = @sp and mavtu = @vt"
‘ thứ tự đưa tham số vào tùy ý vì phải chỉ đúng tên tham số trong lệnh SQL
Dim ts1 As SqlClient.SqlParameter = lenh.Parameters.Add("@vt", _
SqlDbType.Char, 4)
ts1.Value = "S001"
Dim ts2 As SqlClient.SqlParameter = lenh.Parameters.Add("@sp", _
SqlDbType.Char, 4)
ts2.Value = "PN01"

II.3.4. Tạo tham số và đưa vào tập hợp Parameters


Ví dụ: Thủ tục nội spSLGiao cần hai tham số đầu vào: @sodh, @mavtu và trả về số lượng đã giao của
mặt hàng @mavtu cho đơn đặt hàng @sodh. Vì vậy chúng ta phải truyền vào 3 tham số: 1 tham số trả
về và 2 tham số đầu vào. Tham số trả về phải được truyền cho Command trước tiên.

lenh.CommandText = "spSLGiao"

Học phần 3 – VB.NET Trang 94/187


Tài liệu hướng dẫn giảng dạy

lenh.CommandType = CommandType.StoredProcedure
Dim tv As New OleDbParameter()
tv.Direction = ParameterDirection.ReturnValue
tv.OleDbType = OleDb.OleDbType.Integer
lenh.Parameters.Add(tv)
Dim ts1 As OleDbParameter = lenh.Parameters.Add("@sodh", _
OleDbType.Char, 4)
ts1.Value = "D001"
Dim ts2 As OleDbParameter = lenh.Parameters.Add("@mavtu", _
OleDbType.Char, 4)
ts2.Value = "C001"

II.4. Thực hiện Command


Command có nhiều phương thức thực hiện khác nhau như sau:

II.4.1. ExecuteNonquery
Để gọi thực hiện các câu truy vấn cập nhật INSERT, UPDATE, DELETE,... hay thủ tục nội không trả về
dữ liệu hoặc khi chúng ta không quan tâm đến dữ liệu trả về. Tuy không trả về dữ liệu, nhưng các
tham số đầu ra, trả về đều chứa dữ liệu (nếu có). Với các lệnh INSERT, UPDATE, DELETE, phương thức
này trả về số dòng chịu tác động của Command, ngược lại phương thức trả về -1:
Ví dụ: Trong ví dụ trên, chúng ta nhận được số lượng mặt hàng "C001" đã giao cho đơn đặt hàng
“D001” khi goi thực hiện như sau.

cmd.ExecuteNonQuery()
Console.WriteLine("Số lượng đã giao {0}", tv.Value)

II.4.2. ExecuteReader
Phương thức này trả về một đối tượng DataReader để đọc dữ liệu mỗi lần một dòng với phương thức
Read(). DataReader đọc dữ liệu trực tiếp từ nguồn dữ liệu nên phải duy trì kết nối cho đến khi đọc
xong. Cú pháp gọi phương thức này như sau.
Cú pháp:

ExecuteReader()

Hoặc

ExecuteReader(<behavior>)

Các giá trị của <behavior>


Giá trị Mô tả
CloseConnection Khi đối tượng DataReader đóng lại, Connection tự động đóng theo.
Dim bo_doc As New OledbReader = _
lenh.ExecuteReader(CommandBehavior.CloseConnection)
Dim ndung As String, i As Short
Do While bo_doc.Read

Học phần 3 – VB.NET Trang 95/187


Tài liệu hướng dẫn giảng dạy

For i = 0 To bo_doc.FieldCount -1
ndung &= bo_doc.GetValue(i) & vbTab
Next
ndung &= vbNewLine
Loop
bo_doc.Close()
MsgBox (lenh.Connection.State) ' trả về Closed

Default Tương tự như khi gọi ExecuteReader()


SchemaOnly Truy vấn chỉ trả về cấu trúc các cột và không làm ảnh hưởng đến các thao tác
khác.
Dim bo_doc As New OledbReader = _
lenh.ExecuteReader(CommandBehavior.SchemaOnly)
Dim ndung As String, i As Short
For i = 0 To bo_doc.FieldCount -1
ndung &= bo_doc.GetName(i) & vbNewLine
Next

II.4.3. ExecuteScalar
Phương thức này thực hiện lệnh của Command và chỉ trả về giá trị của cột đầu tiên và dòng đầu tiên.
Chúng ta thường gọi phương thức này khi muốn Command thực hiện các hàm tính toán thống kê SUM,
COUNT, AVG, MAX, MIN, ... trên nguồn dữ liệu ngay lúc thực thi.
Cú pháp:

ExecuteScalar()

Ví dụ:

lenh.CommandText = "Select Sum(slnhap*dgnhap) from CTNHAP where sopn = ?"


lenh.Parameters.Add("pn", "PN01")
Dim kq As Integer = lenh.ExecuteScalar()
Console.WriteLine("Trị giá của phiếu nhập {0} là {1:#,###}", _
lenh.Parameters(0).Value, kq)

II.5. DataReader
Là đối tượng truy cập dữ liệu trực tiếp, sử dụng cursor phía Server và duy trì kết nối với Server trong
suốt quá trình đọc dữ liệu, DataReader thuộc không gian tên System.Data.OledbDataReader hoặc
System.Data.SqlDataReader

Học phần 3 – VB.NET Trang 96/187


Tài liệu hướng dẫn giảng dạy

II.5.1. Các thuộc tính của DataReader


Các thuộc tính
Tên Mô tả
FieldCount Trả về số cột trên dòng hiện hành của DataReader.
IsClosed Cho biết DataReader đã đóng chưa.
Item Trị của cột truyền vào. Tham số truyền có thể là tên cột hoặc số thứ tự (từ 0)

II.5.2. Các phương thức của DataReader


Các phương thức
Tên Mô tả
Close Đóng DataReader.
GetFieldType Trả về kiểu dữ liệu của cột truyền vào.
GetName Trả về tên của cột truyền vào.
GetOrdinal Trả về số thứ tự của cột truyền vào (bắt đầu từ 0).
GetSchemaTable Trả về bảng chứa thông tin mô tả cột của DataReader.
GetValue Trả về giá trị trên cột truyền vào.
Read Di chuyển đến dòng kế tiếp và trả về True nếu còn dòng để di chuyển, ngược
lại trả về False

Trong khi DataReader đang mở, các thao tác dữ liệu khác trên nguồn dữ liệu đều không thể cho đến
khi DataReader đóng lại bằng lệnh Close.

III. DataAdapter
Để lấy dữ liệu từ nguồn dữ liệu về cho ứng dụng, chúng ta sử dụng một đối tượng gọi là DataAdapter.
Đối tượng này cho phép lấy cấu trúc và dữ liệu của các bảng trong nguồn dữ liệu.
DataAdapter là một bộ gồm bốn đối tượng Command:
– SelectCommand: cho phép lấy thông tin từ nguồn dữ liệu về
– InsertCommand: cho phép thêm dữ liệu vào bảng trong nguồn dữ liệu.
– UpdateCommand: cho phép sửa đổi dữ liệu trên bảng trong nguồn dữ liệu.
– DeleteCommand: cho phép hủy bỏ dữ liệu trên bảng trong nguồn dữ liệu.
Thông thường, chúng ta chỉ cần khai báo nội dung lệnh cho SelectCommand, các nội dung của các
command còn lại có thể được phát sinh nhờ đối tượng CommandBuilder dựa vào nội dung của
SelectCommand.

III.1. Tạo DataAdapter


Cũng như Command, chúng ta cần khai báo rõ DataAdapter sử dụng theo Data Provider nào:
SqlDataAdapter hoặc OledbDataAdapter. Hai lớp này thuộc không gian tên:

ƒ System.Data.OleDb.OleDbDataAdapter

Học phần 3 – VB.NET Trang 97/187


Tài liệu hướng dẫn giảng dạy

ƒ System.Data.SqlClient.SqlDataAdapter
Cú pháp:

New <loại>DataAdapter()
New <loại>DataAdapter(<đối tượng SelectCommand>)

<đối tượng SelectCommand>: Đối tượng Command có sẵn với nội dung lệnh truy xuất.

New <loại>DataAdapter(<lệnh>, <đối tượng Connection>)

<lệnh>: Câu lệnh SQL, tên storedprocedure… để thực hiện truy xuất từ nguồn dữ liệu
<đối tượng Connection>: Đối tượng Connection, trên đó DataAdapter thao tác với nguồn dữ liệu

New <loại> DataAdapter(<lệnh>,<chuỗi Connection>)

<chuỗi Connection>: Chuỗi ConnectionString để tạo một đối tượng Connection


DataAdapter chỉ thao tác được với nguồn dữ liệu qua một đối tượng Connection đang kết nối, nhưng
điểm đặc biệt của DataAdapter là khi Connection chưa mở, DataAdapter sẽ tự động mở kết nối khi cần
và tự động đóng lại, ngược lại, với một Connection đã mở sẵn, chúng ta phải tự đóng kết nối,
DataAdapter không thực hiện tự động.
Ví dụ:

Dim bo_doc_ghi As New OledbDataAdapter()


bo_doc_ghi.SelectCommand.CommandText = "Select * from VATTU"
bo_doc_ghi.SelectCommand.Connection.ConnectionString = _
"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\QlHanghoa.mdb"

Hoặc

Dim lenh As New OledbCommand("Select * from VATTU", _


"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\QlHanghoa.mdb")
Dim bo_doc_ghi As New OledbDataAdapter(lenh)

Hoặc

Dim ketnoi As New OledbConnection("Provider =Microsoft.Jet.OLEDB.4.0;" & _


"Data Source = C:\QlHanghoa.mdb")
Dim bo_doc_ghi As New OledbDataAdapter("Select * from VATTU", ketnoi)

Hoặc

Dim chuoi As String = "Provider = Microsoft.Jet.OLEDB.4.0; " & _


"Data Source= C:\QlHanghoa.mdb"
Dim bo_doc_ghi As New OledbDataAdapter(“Select * from VATTU”, chuoi)

III.2. Các thuộc tính chính của DataAdapter


Các thuộc tính chính

Tên Mô tả
ContinueUpdateOnError Chỉ định cách thức xử lý khi DataAdapter cập nhật dữ liệu về nguồn và bị
lỗi. Nếu là True, DataAdapter bỏ qua dòng bị lỗi và cập nhật các dòng kế

Học phần 3 – VB.NET Trang 98/187


Tài liệu hướng dẫn giảng dạy

tiếp. Lỗi phát sinh sẽ được đưa vào thuộc tính RowError của dòng bị lỗi,
ngược lại False, sẽ phát sinh Exception khi dòng bị lỗi.
DeleteCommand Đối tượng Command chứa nội dung lệnh hủy các mẩu tin trên nguồn dữ
liệu.
InsertCommand Đối tượng Command chứa nội dung lệnh chèn các mẩu tin mới vào nguồn
dữ liệu.
SelectCommand Đối tượng Command chứa nội dung lệnh truy xuất các mẩu tin từ nguồn
dữ liệu.
TableMappings Tập hợp các ánh xạ tên bảng khi DataAdapter đổ dữ liệu hay cấu trúc vào
đối tượng chứa.
UpdateCommand Đối tượng Command chứa nội dung lệnh cập nhật các mẩu tin vào nguồn
dữ liệu.

III.3. Các chức năng của DataAdapter


III.3.1. Để lấy dữ liệu từ nguồn
Sau khi có đối tượng DataAdapter với nội dung SelectCommand và thông tin về kết nối, chúng ta có thể
sử dụng DataAdapter để lấy dữ liệu về cho các đối tượng chứa dữ liệu như DataTable, DataSet qua
phương thức Fill. Phương thức trả về số mẩu tin lấy về được.
Cú pháp:
Đổ dữ liệu vào DataTable có sẵn

Fill(<datatable>)

Đổ dữ liệu vào DataSet có sẵn. Dữ liệu được lấy về Dataset dưới dạng các DataTable, với tên mặc định
là Table,Table1,Table2,…

Fill(<dataset>)

Đổ dữ liệu vào DataSet cho bảng <tên Datatable>; nếu chưa có, bảng sẽ được tạo

Fill(<dataset>, <tên Datatable>)

Ví dụ: Tiếp tục với của phần trước

Dim dst As New DataSet()


Dim so As Integer
so = bo_doc_ghi.Fill(dst, "Vattu")


Kinh nghiệm giảng dạy:
Khi dùng nhiều DataAdapter để đổ dữ liệu của nhiều bảng vào DataSet, nếu không chỉ
rõ đổ vào bảng nào trong DataSet, dữ liệu sẽ đổ chung vào một bảng, số cột là tổng số
cột có tên khác nhau trong các bảng từ nguồn dữ liệu, trên mỗi dòng cột nào không có
dữ liệu tương ứng sẽ mang trị Null.

Học phần 3 – VB.NET Trang 99/187


Tài liệu hướng dẫn giảng dạy

Ví dụ: Tiếp tục với của phần trước

Dim dst As New DataSet()


Dim ketnoi As New OledbConnection("Provider =Microsoft.Jet.OLEDB.4.0;" & _
"Data Source = C:\QlHanghoa.mdb")
Dim bo_doc_ghi1 As New OledbDataAdapter("Select * from NHACC", ketnoi)
Dim bo_doc_ghi2 As New OledbDataAdapter("Select * from VATTU", ketnoi)
bo_doc_ghi1.Fill(dst)
bo_doc_ghi2.Fill(dst)

Dữ liệu trên bảng của DataSet có dạng


Kinh nghiệm giảng dạy:

Chúng ta có
thể dùng
một
DataAdapter
để đổ dữ
liệu của
nhiều bảng
từ SQL
Server vào
DataSet với
nội dung
lệnh truy
vấn là các
lệnh liên
tiếp và cách
nhau bằng
dấu (;)

Ví dụ:
Học phần 3 – VB.NET Trang 100/187
Tài liệu hướng dẫn giảng dạy

Dim dst As New DataSet()


Dim ketnoi As New OledbConnection("Provider =SQLOLEDB; " & _
"Data Source=(local); Integrated Security=SSPI;" & _
"Initial Catalog=Trac_nghiem;Persist Security Info=False")
Dim bo_doc_ghi As New OledbDataAdapter("Select * From VATTU;" & _
"Select * from NHACC", ketnoi)
bo_doc_ghi.Fill(dst)

Với lệnh Fill như trên (không có tên bảng), dữ liệu đổ về DataSet dưới hình thức các DataTable có tên
lần lượt Table, Table1,…

Với lệnh Fill sau đây (có tên bảng)

bo_doc_ghi.Fill(dst, "Vattu")

Dữ liệu đổ về DataSet dưới hình thức các DataTable có tên lần lượt Vattu, Vattu1,…
Để đặt lại tên cho các bảng, chúng ta có thể dùng cách ánh xạ tên bảng như sau trước khi đổ dữ liệu:
Cho trường hợp không có tên bảng (sử dụng bo_doc_ghi.Fill(dst))

bo_doc_ghi.TableMappings.Add (“Table”, “Vattu”)


bo_doc_ghi.TableMappings.Add ("Table1", "Nhacc")

III.3.2. Để lấy cấu trúc từ nguồn dữ liệu


Cú pháp:
Tạo cấu trúc dữ liệu cho DataSet có sẵn, phương thức trả về một tập hợp các cấu trúc bảng được thêm
vào DataSet

FillSchema(<dataset>, <kiểu cấu trúc>)

Tạo cấu trúc dữ liệu cho DataTable có sẵn, phương thức trả về DataTable

FillSchema(<datatable>, <kiểu cấu trúc>)

Tạo cấu trúc dữ liệu cho bảng <tên Datatable> trong DataSet; nếu chưa có, bảng sẽ được tạo ra

FillSchema(<datatable>, <tên Datatable>,<kiểu cấu trúc>)

<kiểu cấu trúc>: Qui định việc ánh xạ tên có được chấp nhận hay không.

Các giá trị của <kiểu cấu trúc>


Giá trị Mô tả
SchemaType.Mapped Sử dụng các TableMappings cho các cấu trúc đưa vào DataSet nếu trùng
hợp.
SchemaType.Source Không sử dụng các TableMappings

Thông thường SchemaType.Mapped được sử dụng


Nếu bảng đã có cấu trúc sẵn, các cột có tên khác với cột có sẵn trên bảng sẽ được thêm vào.
Tùy theo cấu trúc trên nguồn dữ liệu, những thuộc tính sau sẽ được đưa vào cấu trúc của cột:
ƒ AllowDBNull: cho phép nhận giá trị Null hay không

Học phần 3 – VB.NET Trang 101/187


Tài liệu hướng dẫn giảng dạy

ƒ AutoIncrement: tự động tăng


ƒ MaxLength: kích thước tối đa của cột (tính theo Byte)
ƒ ReadOnly: chỉ cho phép đọc
ƒ Unique: cột có trị duy nhất
Phương thức FillSchema cũng định luôn khóa chính và các ràng buộc cho bảng theo nguyên tắc sau:
ƒ Các cột khóa chính trong lệnh truy vấn của SelectCommand được dùng làm các cột khóa chính
cho bảng.
ƒ Nếu không có cột khóa chính trong lệnh truy vấn, nhưng có những cột có trị duy nhất và nếu
những cột này không cho phép nhận giá trị Null, thì được dùng làm khóa chính. Ngược lại, mỗi
một cột tuy có trị duy nhất nhưng chấp nhập giá trị Null, thì một ràng buộc duy nhất được thêm
vào tập hợp Constraints của bảng nhưng không có khóa chính.
Chỉ có các ràng buộc khóa chính và khóa duy nhất mới thêm vào tập hợp Constraints, các loại ràng
buộc khác không được đưa vào.
Những đặc điểm của phương thức FillSchema cũng giống như của Fill
Ví dụ:

Dim dst As New DataSet()


Dim ketnoi As New OledbConnection("Provider =SQLOLEDB; " & _
"Data Source=(local); Integrated Security=SSPI;" & _
"Initial Catalog=Trac_nghiem;Persist Security Info=False")
Dim bo_doc_ghi As New OledbDataAdapter("Select * From VATTU;" & _
"Select * from NHACC", ketnoi)
bo_doc_ghi.TableMappings.Add ("Table", "Vattu")
bo_doc_ghi.TableMappings.Add ("Table1", "Nhacc")

Khi sử dụng giá trị SchemaType.Source, bo_doc_ghi sẽ lấy cấu trúc về cho các bảng trong DataSet và
đặt tên các bảng theo cách mặc nhiên Table, Table1

bo_doc_ghi.FillSchema(dst,SchemaType.Source)

Khi sử dụng giá trị SchemaType.Mapped, bo_doc_ghi sẽ lấy cấu trúc về cho các bảng trong DataSet và
đặt tên các bảng lần lượt theo TableMappings đã tạo: Vattu, Nhac

bo_doc_ghi.FillSchema(dst,SchemaType.Mapped)

III.3.3. Tạo bộ lệnh cập nhật cho DataAdapter:


Để tự động phát sinh lệnh cập nhật cho các command còn lại của DataAdapter, chúng ta sử dụng
CommandBuilder thuộc không gian tên:

System.Data.Oledb.OledbCommandBuilder
System.Data.SqlClient.SqlCommandBuilder

Cách thực hiện như sau:


Cú pháp:

New <loại>CommandBuilder(<đối tượng DataAdapter>)

Ví dụ:

Học phần 3 – VB.NET Trang 102/187


Tài liệu hướng dẫn giảng dạy

Imports System.Data.Oledb

Dim chuoi As String = "Provider = Microsoft.Jet.OLEDB.4.0; " & _
"Data Source = C:\QlHanghoa.mdb"
Dim bo_doc_ghi As New OledbDataAdapter("Select * from VATTU", chuoi)
Dim bo_phat_sinh As New OledbCommandBuilder(bo_doc_ghi)

Mỗi DataAdapter chỉ có thể kết hợp với một CommandBuilder. Đối tượng này dùng nội dung lệnh trong
SelectCommand của DataAdapter để tạo nội dung lệnh cho các Command còn lại với các đặc điểm sau:
ƒ CommandBuilder chỉ phát sinh nội dung lệnh cập nhật cho các DataAdapter có nội dung
SelectCommand truy xuất đến chỉ một bảng nguồn
ƒ Nội dung trong SelectCommand phải có ít nhất một khóa chính hoặc một khóa duy nhất
(Unique key) để DataAdapter phân biệt các dòng khi cập nhật. Nếu không, CommandBuilder sẽ
không phát sinh được nội dung lệnh cho các Command Insert, Update, Delete.
ƒ Trường hợp nội dung của SelectCommand là truy vấn từ hơn một bảng hoặc từ một
StoredProcedure, các Command cập nhật không tự động phát sinh, nhưng chúng ta phải khai
báo các Command cập nhật cách tường minh.
ƒ Sau khi lệnh được phát sinh, nếu nội dung lệnh của SelectCommand thay đổi, lệnh của các
Command khác không tự động thay đổi theo cho đến khi phương thức RefreshSchema của
CommandBuilder được gọi.
ƒ Trường hợp nội dung của SelectCommand là nhiều câu Select SQL, CommandBuilder chỉ tạo
được lệnh cập nhật cho lệnh truy vấn đầu tiên.
Ví dụ: cách thức CommandBuilder phát sinh lệnh cho các Command

Dim chuoi As String = "Provider=Microsoft.Jet.OLEDB.4.0;" & _


"Data Source = C:\QlHanghoa.mdb"
Dim bo_doc_ghi As New OledbDataAdapter("Select * from VATTU", chuoi)
Dim bo_phat_sinh As New OledbCommandBuilder(bo_doc_ghi)
Console.WriteLine(bo_phat_sinh.GetInsertCommand.CommandText)
' kết quả in ra
' INSERT INTO VATTU( mavtu , tenvtu , dvtinh ) VALUES ( ? , ? , ? )

Console.WriteLine(bo_phat_sinh.GetUpdateCommand.CommandText)
' kết quả in ra
' UPDATE VATTU SET mavtu = ? , tenvtu = ? , dvtinh = ? WHERE ( (mavtu = ?)
' AND ((? = 1 AND tenvtu IS NULL) OR (tenvtu = ?))
' AND ((? = 1 AND dvtinh IS NULL) OR (dvtinh = ?)) )

Console.WriteLine(bo_phat_sinh.GetDeleteCommand.CommandText)
' kết quả in ra
' DELETE FROM VATTU WHERE ( (mavtu = ?) AND (( ? = 1 AND tenvtu IS NULL)
' OR (tenvtu = ?)) AND (( ? = 1 AND dvtinh IS NULL) OR (dvtinh = ?)) )

III.3.4. Để cập nhật các thay đổi về nguồn dữ liệu

Học phần 3 – VB.NET Trang 103/187


Tài liệu hướng dẫn giảng dạy

Cú pháp:

Update(<mảng dòng>)

Phương thức này cập nhật các dòng <mảng dòng> vào nguồn dữ liệu
<mảng dòng>: Mảng các đối tượng lớp DataRow, thường mảng này là kết quả trả về của phương thức
GetChanges của DataSet

Update(<dataset>)

Phương thức này cập nhật các thay đổi trên tất cả các bảng của <dataset> vào nguồn dữ liệu
<dataset>: Đối tượng DataSet mà DataAdapter sẽ cập nhật vào nguồn

Update(<datatable>)

Phương thức này cập nhật các thay đổi trên DataTable vào nguồn dữ liệu
<datatable>: Đối tượng DataTable mà DataAdapter sẽ cập nhật vào nguồn

Update(<dataset>, <tên bảng>)

Phương thức này cập nhật các thay đổi trên bảng có tên <tên bảng> trong DataSet vào nguồn dữ liệu
Khi phương thức Update được gọi, DataAdapter sẽ kiểm tra tình trạng các dòng là thêm mới, sửa đổi,
xóa và gọi thực hiện tự động các Command tương ứng cho mỗi dòng. Nếu các Command chưa được
tạo sẽ phát sinh lỗi. Chúng ta có thể tạo và gán cho mỗi loại Command trên DataAdapter hoặc tự động
phát sinh thông qua CommandBuilder như đề cập ở mục trên.
Thông thường, mỗi Command trên DataAdapter có một tập hợp tham số kết hợp với nó. Các tham số
này được ánh xạ với dòng đang cập nhật thông qua thuộc tính:
ƒ SourceColumn: Cho biết tên cột trên dòng được cập nhật liên kết với tham số
ƒ SourceVersion: Cho biết giá trị của phiên bản nào trên dòng được cập nhật truyền vào vị trí
tham số.
Các giá trị của SourceVersion
Giá trị Mô tả
Current Tham số dùng giá trị hiện hành của cột. Đây là giá trị mặc định.
Default Tham số dùng giá trị mặc định đã qui định cho cột.
Original Tham số dùng giá trị gốc: giá trị từ khi bảng được lấy về từ nguồn dữ liệu
hay từ lần gọi cập nhật lần trước.
Proposed Tham số sử dụng một giá trị đề nghị.

Học phần 3 – VB.NET Trang 104/187


Tài liệu hướng dẫn giảng dạy

Bài 6
DATASET, DATATABLE,
DATARELATION VÀ DATAVIEW
Tóm tắt
Lý thuyết 6 tiết - Thực hành 5 tiết

Mục tiêu Các mục chính Bài tập

Kết thúc bài học này, học viên có thể 1. DataSet 3.3, 4.2, 4.3
làm việc với dữ liệu thông qua các đối 2. DataTable
tượng ADO.NET
3. DataRelation
4. DataView

Học phần 3 – VB.NET Trang 105/187


Tài liệu hướng dẫn giảng dạy

I. DataSet
Một trong những điểm khác biệt chính giữa ADO và ADO.NET là đối tượng DataSet. Như đã trình bày ở
chương trước, DataSet là một mô hình CSDL quan hệ thu nhỏ đáp ứng nhu cầu của ứng dụng.
DataSet chứa các bảng (DataTable), các quan hệ (DataRelation). DataSet thuộc không gian tên sau:
SysTem.Data

Dataset trong hệ thống không gian tên

I.1. Khai báo DataSet


Cú pháp:

New SysTem.Data.DataSet()

Hoặc

New SysTem.Data.DataSet(<tên>)

<tên>: tên của DataSet

I.2. Các thuộc tính của DataSet


Các thuộc tính chính
Tên Mô tả
DataSetName Tên của DataSet. (đọc ghi)
HasErrors Giá trị cho biết có lỗi xảy ra trên một trong các bảng của DataSet: True/False
(chỉ đọc)
Relations Tập hợp các quan hệ (DataRelation) một nhiều của DataSet. (chỉ đọc)
Tables Tập hợp các bảng (DataTable) của DataSet. (chỉ đọc)

I.3. Các phương thức của DataSet


I.3.1. Thêm một bảng vào DataSet:
Muốn đưa một DataTable vào DataSet, chúng ta dùng phương thức Add của tập hợp Tables.
Cú pháp:

<Dataset>.Tables.Add()

Một bảng mới tự động tạo ra với tên mặc nhiên (Table1, Table2,…) và đưa vào tập hợp Tables của

Học phần 3 – VB.NET Trang 106/187


Tài liệu hướng dẫn giảng dạy

DataSet

<Dataset>.Tables.Add(<tên bảng>)

Một bảng mới tự động tạo ra với tên là <tên bảng> và đưa vào tập hợp Tables

<Dataset>.Tables.Add(<bảng>)

Đưa <bảng> vào tập hợp Tables


<bảng>: là một đối tượng DataTable muốn đưa vào DataSet (sẽ đề cập đến trong phần sau)


Kinh nghiệm giảng dạy:
Tên bảng trong DataSet có phân biệt chữ HOA chữ thường. Nghĩa là có thể có 2 bảng
tên "table1" và "Table1"

Ví dụ:

Imports SysTem.Data

Dim dst As New DataSet("Ví dụ")
Dim bang As New DataTable("Bảng 1")
Dst.Tables.Add(bang)

I.3.2. Thêm nhiều bảng vào DataSet:


Muốn đưa nhiều bảng vào DataSet, chúng ta dùng phương thức AddRange của tập hợp Tables.
Cú pháp:

<DataSet>.Tables.AddRange(<mảng DataTable>)

<mảng DataTable>: Là một mảng các DataTable đã tạo ra muốn đưa vào DataSet
Ví dụ:

Dim dst As New DataSet("Ví dụ")


Dim bang1 As New DataTable("Bảng 1")
Dim bang2 As New DataTable("Bảng 2")
dst.Tables.AddRange(New DataTable(){bang1,bang2})

I.3.3. Xóa bảng khỏi DataSet:


Để xóa một bảng khỏi DataSet, chúng ta dùng các phương thức sau của tập hợp Tables.

Cú pháp:
Xóa <DataTable> khỏi tập hợp Tables của DataSet.

<DataSet>.Tables.Remove(<DataTable>)

Xóa <DataTable> có tên là <tên bảng> khỏi tập hợp Tables của DataSet.

<DataSet>.Tables.Remove(<tên bảng>)

Xóa <DataTable> có chỉ số là <chỉ số> khỏi tập hợp Tables của DataSet.

Học phần 3 – VB.NET Trang 107/187


Tài liệu hướng dẫn giảng dạy

<DataSet>.Tables.RemoveAt(<chỉ số>)

Tuy nhiên, bảng có thể đang hiển thị dữ liệu trên Form nên chúng ta cần kiểm tra xem có thể xóa được
không với cú pháp:

<DataSet>.Tables.CanRemove(<DataTable>)

Phương thức trả về True có thể xóa, ngược lại là False.


Ví dụ:

Dim bang As DataTable = dst.Tables(0)


If dst.Tables.CanRemove(bang) then
dst.Tables.Remove(bang)
End If

I.3.4. Xóa tất cả các bảng khỏi DataSet


Để xóa tất cả các bảng khỏi DataSet, chúng ta dùng các phương thức sau của tập hợp Tables.
Cú pháp:

<DataSet>.Tables.Clear()

I.3.5. Kiểm tra bảng có thuộc về DataSet


Cú pháp:

<DataSet>.Tables.Contains(<tên DataTable>)

Phương thức trả về True nếu trong Tables có DataTable có tên <tên DataTable>, ngược lại là False.

I.3.6. Lấy chỉ số của bảng


Cú pháp:

<DataSet>.Tables.IndexOf(<tên DataTable>)

Phương thức trả về chỉ số của DataTable có tên <tên DataTable>.

<DataSet>.Tables.IndexOf(<DataTable>)

Phương thức trả về chỉ số của <DataTable>.

I.3.7. Lấy số bảng chứa trong DataSet


Cú pháp:

<DataSet>.Tables.Count

I.3.8. Để kiểm tra dữ liệu của DataSet có thay đổi


Cú pháp:

<DataSet>.HasChanges()

Phương thức kiểm tra sự thay đổi của tất cả các dòng dữ liệu trên các bảng (thêm mới, xóa bỏ, sửa
đổi) và trả về True nếu có, ngược lại False.

<DataSet>.HasChanges(<trạng thái dòng>)

Học phần 3 – VB.NET Trang 108/187


Tài liệu hướng dẫn giảng dạy

Phương thức kiểm tra sự thay đổi của tất cả các dòng dữ liệu trên các bảng có trạng thái như <trạng
thái dòng> và trả về True nếu có, ngược lại False..

I.3.9. Lấy ra dòng dữ liệu đã thay đổi trong DataSet


Cú pháp:

<DataSet>.GetChanges()

Phương thức trả về bản sao của DataSet gồm những dòng dữ liệu đã bị thay đổi trên các bảng (do
thêm mới, xóa bỏ, sửa đổi).

<DataSet>.GetChanges(<trạng thái dòng>)

Phương thức trả về bản sao của DataSet gồm những dòng dữ liệu đã bị thay đổi có trạng thái như
<trạng thái dòng>.

Ví dụ:

Dim ds As DataSet
If dst.HasChanges() then ds = dst.GetChanges()

If dst.HasChanges(DataRowState.Modified) then
ds = dst.GetChanges(DataRowState.Modified)
End If

I.3.10. Để cập nhật các thay đổi trên DataSet


Cú pháp:

<DataSet>.AcceptChanges()

Phương thức cập nhật các thay đổi kể từ lúc lấy dữ liệu về hoặc từ lần gọi AcceptChanges trước.

Trên DataTable, DataRow cũng có phương thức tương ứng. Khi gọi AcceptChanges của DataSet sẽ kéo
theo gọi AcceptChanges của DataTable, đến lượt kéo theo gọi AcceptChanges của DataRow.

I.3.11. Để hủy bỏ các thay đổi trên DataSet:


Cú pháp:

<DataSet>.RejectChanges()

Phương thức này của DataSet phục hồi tất cả các thay đổi kể từ lúc lấy dữ liệu về hoặc từ lần gọi
AcceptChanges trước.

Khi gọi RejectChanges của DataSet sẽ kéo theo gọi RejectChanges của DataTable, DataRow.

I.3.12. Để trộn dữ liệu bên ngoài vào DataSet


Dữ liệu bên ngoài có thể là các dòng (mảng dòng), DataTable hoặc một DataSet khác.
Nguyên tắc của phương thức này như sau: khi được gọi, cấu trúc của nguồn và đích được so sánh với
nhau. Nếu cấu trúc dữ liệu bên ngoài khác với cấu trúc của DataSet do thêm cột, các cột mới sẽ được
thêm vào DataSet (tùy cú pháp) cùng với dữ liệu. Trên dữ liệu bên ngoài, những dòng có tình trạng
Unchanged, Modified và Deleted phải có cột khóa chính như những dòng đã có trên DataSet. Những
dòng có tình trạng Added (thêm mới) phải thỏa ràng buộc về khóa chính của DataSet.

Học phần 3 – VB.NET Trang 109/187


Tài liệu hướng dẫn giảng dạy

Trong quá trình trộn lẫn dữ liệu, các ràng buộc được bỏ qua: thuộc tính EnforceConstraints có giá trị
False. Cuối quá trình, nếu ràng buộc nào không thể chuyển lại True sẽ làm phát sinh một Exception. Vì
vậy, chúng ta cần giải quyết các vi phạm ràng buộc trước khi gán EnforceConstraints với giá trị True.
Phương thức này có rất nhiều cách sử dụng.

Cú pháp:

<DataSet>.Merge(<mảng dòng>)

Trộn một mảng các dòng vào DataSet.

<DataSet>.Merge(<DataTable>)

Trộn một DataTable bên ngoài vào DataSet.

<DataSet>.Merge(<DataSet>)

Trộn một Dataset bên ngoài vào DataSet.

<DataSet>.Merge(<DataSet>,<giữ thay đổi>)

Trộn một Dataset bên ngoài và cấu trúc của nó vào DataSet.
<giữ thay đổi>: nếu là True, các thay đổi từ bên ngoài được giữ nguyên trên DataSet, là False không
thay đổi theo bên ngoài.

<DataSet>.Merge(<DataSet>,<giữ thay đổi>,<xử lý khi cấu trúc khác nhau>)

Trộn một Dataset bên ngoài và cấu trúc của nó vào DataSet.
<xử lý khi cấu trúc khác nhau>: tùy theo giá trị truyền vào.

<DataSet>.Merge(<mảng dòng>,<giữ thay đổi>,<xử lý khi cấu trúc khác nhau>)

Trộn một mảng dòng bên ngoài và cấu trúc của nó vào DataSet.

<DataSet>.Merge(<DataTable>,<giữ thay đổi>,<xử lý khi cấu trúc khác nhau>)

Trộn một DataTable bên ngoài và cấu trúc của nó vào DataSet.

Các giá trị của <xử lý khi cấu trúc khác nhau>

Tên Mô tả
Add Nếu khác nhau, thêm các cột mới vào cấu trúc của DataSet.
Error Nếu khác nhau phát sinh lỗi.
Ignore Nếu khác nhau, bỏ qua các cột mới.

I.3.13. Để hủy bỏ DataSet


Cú pháp:

<DataSet>.Dispose()

Khi được gọi, mọi tài nguyên trên vùng nhớ mà DataSet đang sử dụng sẽ được giải phóng.

I.3.14. Để tạo một quan hệ giữa hai bảng trong DataSet:


Để thiết lập quan hệ cha-con giữa hai bảng (DataTable) trong một DataSet, phải thỏa yêu cầu sau:

Học phần 3 – VB.NET Trang 110/187


Tài liệu hướng dẫn giảng dạy

ƒ Field hoặc các Field của bảng cha trong quan hệ phải thỏa yêu cầu tính duy nhất.
ƒ Chỉ có thể thiết lập quan hệ giữa hai bảng trong cùng DataSet
Chúng ta sử dụng phương thức Add của tập hợp Relations trong DataSet với các cú pháp sau.
Cú pháp:

<DataSet>.Relations.Add(<đối tượng DataRelation>)

<đối tượng DataRelation>: đối tượng này phải được tạo sẵn sẽ đề cập ở phần sau

<DataSet>.Relations.Add(<DataColumn trên bảng cha>, <DataColumn trên bảng


con>)

<DataColumn trên bảng cha>, <DataColumn trên bảng con>: Các đối tượng này thuộc lớp
DataColumn sẽ đề cập ở phần sau là các cột tham gia quan hệ trên bảng cha và bảng con tương ứng

<DataSet>.Relations.Add(<mảng DataColumn trên bảng cha>, _


<mảng DataColumn trên bảng con>)

<mảng DataColumn trên bảng cha>, <mảng DataColumn trên bảng con>: Các mảng này là mảng các
cột tham gia quan hệ trên bảng cha và bảng con tương ứng.

<DataSet>.Relations.Add(<tên quan hệ>, <DataColumn trên bảng cha>, _


<DataColumn trên bảng con>)
<DataSet>.Relations.Add(<tên quan hệ>, <mảng DataColumn trên bảng cha>, _
<mảng DataColumn trên bảng con>)
<DataSet>.Relations.Add(<tên quan hệ>, <DataColumn trên bảng cha>, _
<DataColumn trên bảng con>, <tạo ràng buộc>)
<DataSet>.Relations.Add(<tên quan hệ>, <mảng DataColumn trên bảng cha>, _
<mảng DataColumn trên bảng con>, <tạo ràng buộc>)

Mặc định, khi tạo quan hệ giữa hai bảng, các ràng buộc đồng thời được tạo ra cho trên mỗi bảng như
sau:
ƒ Ràng buộc duy nhất trên bảng cha dựa vào các cột của bảng cha tham gia vào quan hệ (nếu
chưa có)
ƒ Ràng buộc khóa ngoại trên bảng con dựa vào các cột trên bảng cha và bảng con trong quan hệ.
Tham số <tạo ràng buộc> cho phép chúng ta quy định có tạo ràng buộc hay không: True có tạo, False
không tạo.

I.3.15. Thêm nhiều quan hệ vào DataSet:


Muốn đưa nhiều quan hệ có sẵn vào DataSet, chúng ta dùng phương thức AddRange của tập hợp
Relations.
Cú pháp:

<DataSet>.Relations.AddRange(<mảng quan hệ>)

<mảng quan hệ>: là một mảng các quan hệ đã tạo ra muốn đưa vào DataSet.

I.3.16. Xóa quan hệ khỏi DataSet


Để xóa một quan hệ khỏi DataSet, chúng ta dùng các phương thức sau của tập hợp Relations.

Học phần 3 – VB.NET Trang 111/187


Tài liệu hướng dẫn giảng dạy

Cú pháp:

<DataSet>.Relations.Remove(<quan hệ>)

Xóa <quan hệ> khỏi tập hợp Relations của Dataset.

<DataSet>.Relations.Remove(<tên quan hệ>)

Xóa quan hệ có tên là <tên quan hệ> khỏi tập hợp Relations.

<DataSet>.Relations.RemoveAt(<chỉ số>)

Xóa quan hệ có chỉ số là <chỉ số> khỏi tập hợp Relations.

Tuy nhiên, quan hệ có thể đang được sử dụng nên chúng ta cần kiểm tra xem có thể xóa được không
với cú pháp:

<DataSet>.Relations.CanRemove(<quan hệ>)

Phương thức trả về True có thể xóa, ngược lại là False.


Để hủy tất cả các quan hệ trong DataSet, chúng ta dùng các phương thức sau của tập hợp Relations:

<DataSet>.Relations.Clear()

I.3.17. Kiểm tra quan hệ có thuộc về DataSet:


Cú pháp:

<DataSet>.Relations.Contains(<tên quan hệ>)

Phương thức trả về True nếu trong Relations có quan hệ tên <tên quan hệ>, ngược lại là False

II. DataTable
Dữ liệu các bảng trong nguồn dữ liệu được lấy về và đưa vào các DataTable. DataTable thuộc không
gian tên System.Data.DataTable
Có các cách khai báo như sau:
Cú pháp:

New DataTable()
New DataTable(<tên bảng>)

II.1. Các thuộc tính của DataTable


Các thuộc tính
Tên Mô tả
CaseSensitive Qui định việc so sánh chuỗi trong bảng có phân biệt chữ Hoa chữ thường.
True có phân biệt, False không phân biệt.
ChildRelations Trả về tập hợp những quan hệ trong đó DataTable đóng vai trò bảng cha
(bảng một).
Columns Trả về tập hợp các cột trong DataTable (thuộc lớp DataColumn).
Constraints Trả về tập hợp các ràng buộc trong DataTable.
DataSet Trả về DataSet chứa DataTable.

Học phần 3 – VB.NET Trang 112/187


Tài liệu hướng dẫn giảng dạy

DefaultView Trả về DataView phát sinh từ DataTable.


HasErrors Cho biết có dòng nào trên DataTable bị lỗi : True có dòng bị lỗi, ngược lại là
False.
ParentRelations Trả về tập hợp những quan hệ trong đó DataTable đóng vai trò bảng con
(bảng nhiều).
PrimaryKey Mảng các cột có chức năng làm khóa chính của DataTable.
Rows Trả về tập hợp các dòng dữ liệu của DataTable.
TableName Tên của DataTable.

II.2. DataColumn
Cấu trúc của bảng là tập hợp các DataColumn với các thuộc tính của chúng. Chúng ta có thể tạo cấu
trúc của bảng từ cấu trúc bảng trong nguồn dữ liệu hoặc tạo lập từ các DataColumn.
DataColumn thuộc không gian tên System.Data.DataColumn

II.2.1. Các thuộc tính của DataColumn


Các thuộc tính
Tên Mô tả
AllowDBNull Thuộc tính cho biết cột có chấp nhận giá trị Null không (đọc ghi).
AutoIncrement Thuộc tính cho biết giá trị cột có tự động tăng khi thêm dòng mới không (đọc
ghi)..
AutoIncrementSeed Giá trị bắt đầu cho cột khi thêm dòng đầu tiên, nếu AutoIncrement là True.
AutoIncrementStep Bước tăng cho dòng thêm mới kế tiếp, nếu AutoIncrement là True.
Caption Tiêu đề của cột.
ColumnName Tên cột.
DataType Kiểu dữ liệu của cột.
DefaultValue Giá trị mặc định cho cột khi thêm một dòng mới.
Expression Biểu thức dùng để tính giá trị cho cột
MaxLength Độ rộng tối đa cho cột kiểu chuỗi.
Ordinal Trả về số thứ tự của cột trong tập hợp DataColumn
ReadOnly Giá trị cho biết cột có được phép sửa đổi sau khi dòng mới được thêm vào.
Table Trả về DataTable chứa cột.
Unique Giá trị cho biết giá trị cột của mỗi dòng có phải là duy nhất.

II.2.2. Tạo mới DataColumn


Cú pháp:

New DataColumn()
New DataColumn(<tên cột>)
New DataColumn(<tên cột>,<kiểu dữ liệu>)

Học phần 3 – VB.NET Trang 113/187


Tài liệu hướng dẫn giảng dạy

New DataColumn(<tên cột>,<kiểu dữ liệu>,<biểu thức>)

<tên cột>: Tên muốn đặt cho cột

<kiểu dữ liệu>: Kiểu dữ liệu của cột.


<biểu thức>: Biểu thức tính giá trị cho cột


Kinh nghiệm giảng dạy:
Kiểu dữ liệu của DataColumn được khai báo thông qua cú pháp
System.Type.GetType("<kiểu dữ liệu>")
Chuỗi kiểu dữ liệu phải đúng như không gian tên, tên lớp có phân biệt chử Hoa chữ
thường
Các khai báo sau đây sẽ bị lỗi:
Dim cot As New DataColumn(“a”, System.Type.GetType(“System.string”))
Æ Phải là System.String
Dim cot As New DataColumn(“a”, System.Type.GetType(“String”))
Æ Phải là System.String
Dim cot As New DataColumn(“a”, System.Type.GetType(“System.Integer”))
Æ Không có System.Integer nhưng System.Int32
Ví dụ:

Dim cotSL As New _


DataColumn("Soluong",System.Type.GetType("System.Double"))
Dim cotDG As New DataColumn("Dongia",System.Type.GetType("System.Double"))
Dim cotTT As New DataColumn("Thanhtien", _
System.Type.GetType("System.Double"),"Soluong * Dongia")

II.2.3. Sử dụng thuộc tính Expression


Để tạo thêm cột tính toán dựa trên các cột đã có, chúng ta có thể tạo thêm cột mới và sử dụng thuộc
tính Expression để tính toán số liệu cho cột mới tạo này.

Thuộc tính Expression cho phép


ƒ Diễn dịch, tính toán dữ liệu từ các cột có sẵn trên DataTable
Ví dụ: Bang_dien_vien có cột Phai kiểu Boolean, chúng ta tạo thêm cột Gioi_tinh để hiển thị "Nam/Nữ"

Bang_dien_vien.Columns.Add("Gioi_tinh",Type. _
GetType("System.String"), "IIF(Phai,'Nam','Nữ')")

ƒ Hiển thị dữ liệu của các bảng khác trong cùng Dataset thông qua quan hệ
Ví dụ: Tạo thêm cột Ten_VK trên Bang_xuat_dien
thông qua quan hệ VO_KICHXUAT_DIEN đã được
tạo và sơ đồ quan hệ các bảng như sau

Học phần 3 – VB.NET Trang 114/187


Tài liệu hướng dẫn giảng dạy

Bang_xuat_dien.Columns.Add("Ten_VK",System.Type.GetType("System.String"),_
"Parent(VO_KICHXUAT_DIEN).Ten_VK")

Có thể sử dụng các hàm sau trong Expression

Các hàm sử dụng trong Expression

Tên Mô tả
CONVERT Chuyển đổi biểu thức sang kiểu dữ liệu của .Net FrameWork theo cú pháp
CONVERT(<biểu thức>, <kiểu dữ liệu>)
<biểu thức>: biểu thức cần chuyển đổi
<kiểu dữ liệu>: kiểu dữ liệu muốn chuyển sang
LEN Lấy độ dài của chuỗi
LEN(<biểu thức>)
ISNULL Kiểm tra biểu thức có trả về trị Null, nếu có hàm trả về giá trị thay thế,
ngược lại trả về chính trị của biểu thức
ISNULL(<biểu thức>, <giá trị thay thế>)
<giá trị thay thế>: trị thay thế khi biểu thức là Null
IIF Sử dụng như hàm IIF của VB.NET
IIF(<biểu thức luận lý>, <giá trị khi biểu thức đúng>, _
<giá trị khi biểu thức sai>)
TRIM Cắt các ký tự trắng ở hai đầu biểu thức
TRIM(<biểu thức>)
SUBSTRING Lấy chuỗi con trong biểu thức
SUBSTRING(<biểu thức>, <vị trí bắt đầu>, <số ký tự>)
<vị trí bắt đầu>: vị trí bắt đầu chuỗi con trên biểu thức
<số ký tự>: số ký tự sẽ lấy cho chuỗi con trên biểu thức

II.3. DataRow
Dữ liệu lưu trữ trong DataTable qua các DataRow.
DataRow thuộc không gian tên System.Data.DataRow. Để tạo một DataRow chúng ta dùng phương
thức AddNew của DataTable. Sau đây là các thuộc tính và các phương thức của DataRow

II.3.1. Các thuộc tính của DataRow


Các thuộc tính
Tên Mô tả
HasErrors Thuộc tính cho biết dòng có đang bị lỗi hay không.
Item Nội dung dữ liệu lưu giữ của cột trên dòng có tên, cột datacolumn hay số thứ
tự cột truyền vào:
<datarow>.Item(<tên>)
<datarow>.Item(<cột>)
<datarow>.Item(<chỉ số>)
Nội dung dữ liệu lưu giữ của cột trên dòng có tên, datacolumn hay số thứ tự

Học phần 3 – VB.NET Trang 115/187


Tài liệu hướng dẫn giảng dạy

cột truyền vào , giá trị trả về theo phiên bản truyền vào:
<datarow>.Item(<tên>,<phiên bản>)
<datarow>.Item(<cột>,<phiên bản>)
<datarow>.Item(<chỉ số>,<phiên bản>)
Phiên bản có các trị sau :
Current: Dòng chứa trị hiện hành.
Default: Dòng chứa phiên bản mặc định.
Đối với dòng có DataRowState là Added, Modified hoặc Current, phiên bản
mặc định là Current.
Đối với dòng có DataRowState là Deleted, phiên bản mặc định là phiên bản
Original.
Đối với dòng có DataRowState là Detached, phiên bản mặc định là phiên bản
Proposed.
Original: Dòng chứa trị gốc.
Proposed: Dòng chứa trị đã chỉnh sửa
ItemArray Tất cả nội dung của DataRow dưới dạng một mảng.
RowError Mô tả nội dung lỗi của dòng, nếu đang bị lỗi.
RowState Trả về tình trạng của DataRow và có các trị sau :
Added: Dòng đã được thêm vào tập hợp Rows nhưng chưa được cập nhật.
Deleted: Dòng đã được đánh dấu hủy bằng phương thức Delete.
Detached: Dòng không thuộc về tập hợp Rows gồm những dòng sau:
Dòng đã được tạo mới nhưng chưa đưa vào tập hợp Rows
Dòng đã bị loại bỏ khỏi tập hợp bằng phương thức Remove, RemoveAt của
bảng
Dòng đã bị đánh dấu hủy bằng Delete và sau đó đã gọi AcceptChanges của
Datarow.
Modified: Dòng đã được sửa đổi nhưng chưa được cập nhật.
Unchanged: Dòng không thay đổi kể từ lúc đọc từ nguồn dữ liệu hoặc từ lần
cập nhật trước.
Table Trả về tên bảng chứa DataRow.

II.3.2. Các phương thức của DataRow


Các phương thức
Tên Mô tả
BeginEdit Bắt đầu chỉnh sửa dòng. Trong chế độ này, mọi sự kiện tạm thời bị ngưng
lại, các kiểm tra tạm thời bỏ qua. Khi người dùng bắt đầu thay đổi nội dung
trên các điều khiển liên kết, phương thức này được ngầm gọi. Ở chế độ này,
và khi EndEdit chưa được gọi, dòng sẽ mang trị các phiên bản Original (giá trị
gốc) và Proposed (giá trị mới đề nghị). Có thể truy xuất các trị này thông qua
thuộc tính Item(<cột>,<phiên bản>)
CancelEdit Hủy bỏ việc chỉnh sửa trên dòng.
Delete Đánh dấu hủy dòng. Khi phương thức được gọi, dòng có RowState là Deleted
EndEdit Chấm dứt việc chỉnh sửa.
GetChildRows Trả về các dòng có quan hệ nhánh con với dòng đang tham chiếu theo các
cú pháp:

Học phần 3 – VB.NET Trang 116/187


Tài liệu hướng dẫn giảng dạy

GetChildRows(<đối tượng DataRelation>)


GetChildRows(<tên DataRelation>)
GetChildRows(<đối tượng DataRelation>, <phiên bản>)
GetChildRows(<tên DataRelation>, <phiên bản>)

GetParentRow Trả về dòng có quan hệ nhánh cha với đối tượng dòng đang tham chiếu theo
các cú pháp:
GetParentRow(<đối tượng DataRelation>)
GetParentRow(<tên DataRelation>)
GetParentRow(<đối tượng DataRelation>, <phiên bản>)
GetParentRow(<tên DataRelation>, <phiên bản>)

IsNull Cho biết trị của cột truyền vào có mang trị Null.
IsNull(<DataColumn>)
IsNull(<chỉ số của DataColumn>)
IsNull(<tên DataColumn >)
IsNull(<DataColumn>, <phiên bản>)

RejectChanges Hủy bỏ các thay đổi từ lần cập nhật trước.

II.4. Constraint
Constraint (ràng buộc) là một quy tắc áp dụng cho một hoặc nhiều cột để bảo đảm tính toàn vẹn dữ
liệu trên DataTable.
Constraint thuộc không gian tên System.Data.Constraint
Có 2 loại Constraint:
ƒ System.Data.ForeignKeyConstraint: ràng buộc khóa ngoại
ƒ System.Data.UniqueConstraint: ràng buộc duy nhất
Những ràng buộc này do chúng ta tạo ra hoặc do thiết lập quan hệ giữa các bảng trong DataSet mà có.
Chúng ta có thể không cho phát sinh ràng buộc bằng tham số <tạo ràng buộc> = False khi thiết lập
quan hệ với phương thức <Dataset>.Relations.Add đã đề cập trong mục tạo quan hệ giữa hai
DataTable trong một Dataset.

Do có 2 loại ràng buộc nên chúng ta có các cú pháp tạo mới khác nhau cho mỗi loại.

II.4.1. ForeignKeyConstraint
Cú pháp:

New ForeignKeyConstraint(<cột bảng cha>, <cột bảng con>)


New ForeignKeyConstraint(<tên>,<cột bảng cha>, <cột bảng con>)
New ForeignKeyConstraint(<mảng cột bảng cha>, _
<mảng cột bảng con>)
New ForeignKeyConstraint(<tên>, <mảng cột bảng cha>, _
<mảng cột bảng con>)

Học phần 3 – VB.NET Trang 117/187


Tài liệu hướng dẫn giảng dạy

<tên>: Tên ràng buộc khóa ngoại


<cột bảng cha>, <cột bảng con>: DataColumn trên DataTable cha, DataTable con tham gia khóa
ngoại
<mảng cột bảng cha>, <mảng cột bảng con>: Mảng các DataColumn trên DataTable cha, DataTable
con tham gia khóa ngoại

II.4.2. Các thuộc tính của ForeignKeyConstraint


Các thuộc tính
Tên Mô tả
AcceptRejectRule Qui định cách xử lý khi phương thức AcceptChanges trên DataTable cha xảy
ra, gồm các trị :
ƒ Cascade : cập nhật dây chuyền trên bảng con
ƒ None : không làm gì cả.

Columns Trả về các cột tham gia khóa ngoại trên DataTable con
ConstraintName Tên của ràng buộc
DeleteRule Qui định cách xử lý khi một DataRow trên DataTable cha bị hủy, có các trị :
ƒ Cascade: Xóa các DataRow tương ứng trên DataTable con
ƒ None: Không làm gì cả.
ƒ SetDefault: Gán trị mặc định của DataColumn cho các dòng trên
DataTable con liên quan đến dòng vừa bị xóa trên bảng cha
ƒ SetNull: Gán trị DBNull cho các dòng trên DataTable con ứng với dòng
vừa bị xóa trên DataTable cha.

RelatedColumns Trả về các cột tham gia khóa ngoại trên DataTable cha.
RelatedTable Trả về DataTable cha.
Table Trả về DataTable con.
UpdateRule Qui định cách xử lý khi một dòng trên bảng cha thay đổi, có các trị:
ƒ Cascade: Cập nhật giá trị thay đổi trên DataTable cha vào các dòng
tương ứng trên DataTable con
ƒ None: Không làm gì cả.
ƒ SetDefault: Gán trị mặc định của cột cho các dòng trên DataTable con
ứng với dòng vừa thay đổi trên DataTable cha
ƒ SetNull: Gán trị DBNull cho các dòng trên DataTable con ứng với dòng
vừa thay đổi trên DataTable cha.

II.4.3. UniqueConstraint
Cú pháp:

New UniqueConstraint(<tên>, <DataColumn>)


New UniqueConstraint(<DataColumn>)
New UniqueConstraint(<tên>, <mảng DataColumn>)
New UniqueConstraint(<mảng DataColumn>)

Học phần 3 – VB.NET Trang 118/187


Tài liệu hướng dẫn giảng dạy

New UniqueConstraint(<tên>, <mảng tên DataColumn>, <khoá chính>)


New UniqueConstraint(<tên>, <DataColumn>, <khoá chính>)
New UniqueConstraint(<tên DataColumn>, <khoá chính>)
New UniqueConstraint(<tên>, <mảng DataColumn>, <khoá chính>)
New UniqueConstraint(<mảng tên DataColumn>, <khoá chính>)

<tên> : tên ràng buộc duy nhất


<DataColumn> : DataColumn trên bảng muốn tạo khóa duy nhất
<mảng DataColumn> : mảng các DataColumn trên bảng muốn tạo khóa duy nhất

<khóa chính> : (True/False) là khóa chính trên bảng

II.4.4. Các thuộc tính của UniqueConstraint


Các thuộc tính
Tên Mô tả
Columns Trả về mảng các cột tham gia khóa duy nhất.
ConstraintName Tên ràng ruộc khóa duy nhất
IsPrimaryKey Khóa duy nhất có đồng thời là khóa chính không : True/False.
Table Trả về tên bảng chứa ràng buộc.

II.5. Tập hợp Columns


Columns là tập hợp chứa các DataColumn trong cấu trúc của DataTable. Mọi tham chiếu đến
DataColumn đều thông qua tập hợp này. Sau đây là một số chức năng của tập hợp Columns

II.5.1. Số cột trong tập hợp


Cú pháp:

<DataTable>.Columns.Count

II.5.2. Tham chiếu DataColumn trong tập hợp


Cú pháp:

<DataTable>.Columns.Item(<tên DataColumn muốn tham chiếu>)


<DataTable>.Columns.Item(<chỉ số DataColumn muốn tham chiếu>)
<DataTable>.Columns(<tên DataColumn muốn tham chiếu>)
<DataTable>.Columns(<chỉ số DataColumn muốn tham chiếu>)

II.5.3. Thêm DataColumn vào cấu trúc DataTable


Cú pháp:

<DataTable>.Columns.Add()

Tạo mới, đưa vào cấu trúc DataTable và trả về một DataColumn mới

<DataTable>.Columns.Add(<tên DataColumn>)

Học phần 3 – VB.NET Trang 119/187


Tài liệu hướng dẫn giảng dạy

Tạo và đưa vào cấu trúc DataTable, một DataColumn mới tên là tham số truyền vào

<DataTable>.Columns.Add(<DataColumn>)

Đưa vào cấu trúc DataTable DataColumn truyền vào

<DataTable>.Columns.Add(<tên DataColumn>,<kiểu dữ liệu>)

Tạo và đưa vào cấu trúc DataTable, một DataColumn mới tên là tham số truyền vào và có kiểu dữ liệu
là kiểu truyền vào

<DataTable>.Columns.Add(<tên DataColumn>,<kiểu dữ liệu>,<biểu thức>)

Tạo và đưa vào cấu trúc DataTable, một DataColumn mới tên là tham số truyền vào, có kiểu dữ liệu là
kiểu truyền vào và trị của DataColumn tính theo biểu thức truyền vào.

II.5.4. Thêm nhiều DataColumn vào cấu trúc DataTable


Cú pháp:

<DataTable>.Columns.AddRange(<mảng DataColumn>)

Đưa vào cấu trúc DataTable, mảng các DataColumn truyền vào.

II.5.5. Kiểm tra có thể loại bỏ DataColumn khỏi cấu trúc DataTable
Cú pháp:

<DataTable>.Columns.CanRemove(<DataColumn>)

Phương thức thực hiện một số kiểm tra như : DataColumn có thuộc về cấu trúc DataTable hay không,
có liên quan đến ràng buộc hoặc quan hệ của DataTable không và trả về kết quả True/False.

II.5.6. Kiểm tra cấu trúc DataTable có DataColumn tên truyền vào
<DataTable>.Columns.Contains(<tên DataColumn>)

Phương thức trả về True/False. Chúng ta dùng phương thức kiểm tra này trước khi thực hiện một
phương thức khác trên DataColumn

II.5.7. Hủy DataColumn khỏi cấu trúc DataTable


<DataTable>.Columns.Remove(<DataColumn>)

Hủy <DataColumn> khỏi cấu trúc DataTable

<DataTable>.Columns.Remove(<tên DataColumn>)

Hủy DataColumn có tên <tên DataColumn> khỏi cấu trúc DataTable

<DataTable>.Columns.RemoveAt(<chỉ số>)

Hủy DataColumn có chỉ số <chỉ số> khỏi cấu trúc DataTable

<DataTable>.Columns.Clear()

Hủy toàn bộ cấu trúc DataTable


Các phương thức trên sẽ gây lỗi nếu hủy DataColumn không được phép (CanRemove trả về False)

Học phần 3 – VB.NET Trang 120/187


Tài liệu hướng dẫn giảng dạy

II.5.8. Minh họa tạo cấu trúc DataTable


Ví dụ: Minh họa tạo cấu trúc các DataTable sau:
ƒ DataTable PHONGBAN gồm các thông tin Mã phòng ban, Tên phòng ban.
ƒ DataTable NHANVIEN gồm các thông tin Mã số NV, Họ, Tên, Phái, Ngày sinh, Hệ số lương,
thuộc phòng ban nào.
Imports System.Data

Dim bang_phong As New DataTable("PHONGBAN")
Dim cot_Ma, cot_Ten As DataColumn
cot_Ma = New DataColumn("Mapb", Type.GetType("System.String"))
cot_Ma.MaxLength = 2
cot_Ten = New DataColumn("Ten_phong", Type.GetType("System.String"))
cot_Ten.MaxLength = 30
bang_phong.Columns.AddRange(New DataColumn(){cot_Ma,cot_Ten})
bang_phong.PrimaryKey = New DataColumn(){cot_Ma}

Dim bang_nhan_vien As New DataTable("NHANVIEN")


Dim cot(2) As DataColumn
cot(0) = New DataColumn("Manv", Type.GetType("System.String"))
cot(1) = New DataColumn("Honv", Type.GetType("System.String"))
cot(2) = New DataColumn("Tennv", Type.GetType("System.String"))
cot(0).MaxLength = 4
cot(1).MaxLength = 25
cot(2).MaxLength = 10
cot(0).AllowDBNull = False
cot(0).Unique = True
bang_nhan_vien.Columns.AddRange(a)
bang_nhan_vien.Columns.Add("Phai", Type.GetType("System.Boolean"))
bang_nhan_vien.Columns.Add("Ngaysinh", Type.GetType("System.DateTime"))
bang_nhan_vien.Columns.Add("Hsluong", Type.GetType("System.Single"))
bang_nhan_vien.Columns.Add("Mapb", Type.GetType("System.String"))
bang_nhan_vien.Columns("Mapb").MaxLength = 2

II.6. Tập hợp Rows


Rows là tập hợp các dòng dữ liệu của DataTable. Mọi tham chiếu đến DataRow đều thông qua tập hợp
này. Sau đây là một số chức năng của tập hợp Rows:

II.6.1. Số DataRow trong tập hợp


Cú pháp:

<DataTable>.Rows.Count

Học phần 3 – VB.NET Trang 121/187


Tài liệu hướng dẫn giảng dạy

II.6.2. Tham chiếu DataRow trong tập hợp


Cú pháp:

<DataTable>.Rows.Item(<chỉ số DataRow muốn tham chiếu>)


<DataTable>.Rows(<chỉ số DataRow muốn tham chiếu>)

II.6.3. Truy xuất trị của ô trên một DataRow


Cú pháp:

<DataTable>.Rows.Item(<chỉ số dòng>)(<chỉ số cột>)


<DataTable>.Rows(<chỉ số dòng>)(<chỉ số cột>)

Các cách sau áp dụng cho cả hai cách thông qua Item và không có Item

<DataTable>.Rows(<chỉ số dòng>)(<tên cột>)


<DataTable>.Rows(<chỉ số dòng>)(<cột>)
<DataTable>.Rows(<chỉ số dòng>)(<chỉ số cột>,<phiên bản>)
<DataTable>.Rows(<chỉ số dòng>)(<tên cột>,<phiên bản>)
<DataTable>.Rows(<chỉ số dòng>)(<cột>,<phiên bản>)

II.6.4. Thêm DataRow vào DataTable


Cú pháp:

<DataTable>.Rows.Add(<DataRow>)

Thêm một dòng có sẵn vào DataTable.

<DataTable>.Rows.Add(<mảng trị>)

Tạo một dòng mới với các trị trong mảng trị ứng với thứ tự các DataColumn và đưa vào tập hợp Rows
của DataTable.

II.6.5. Để chèn dòng vào DataTable tại một vị trí


Cú pháp:

<DataTable>.Rows.InsertAt(<DataRow>,<vị trí>)

Chèn một DataRow có sẵn vào DataTable tại <vị trí>.


Nếu <vị trí> lớn hơn số dòng của DataTable, dòng mới được thêm vào vị trí cuối DataTable.

II.6.6. Hủy DataRow trên DataTable


Cú pháp:

<DataTable>.Rows.Remove(<DataRow>)

Hủy <DataRow> khỏi tập hợp Rows của DataTable.

<DataTable>.Rows.RemoveAt(<chỉ số>)

Hủy DataRow tại vị trí <chỉ số> khỏi DataTable


Phương thức trên là tương tự gọi phương thức Delete và AcceptChanges của Datarow

Học phần 3 – VB.NET Trang 122/187


Tài liệu hướng dẫn giảng dạy

<DataTable>.Rows.Clear()

Hủy toàn bộ các dòng dữ liệu của DataTable

II.6.7. Để kiểm tra trên khóa chính có chứa trị truyền vào
Cú pháp:

<DataTable>.Rows.Contains(<trị>)

Phương thức kiểm tra trên cột khóa chính xem có dòng nào chứa <trị> và trả về True nếu tìm thấy,
ngược lại trả về False

<DataTable>.Rows.Contains(<mảng trị>)

Phương thức kiểm tra trên các cột khóa chính có dòng nào chứa bộ giá trị <mảng trị> và trả về True
nếu tìm thấy, ngược lại trả về False. Thứ tự trị truyền vào phải theo thứ tự các cột khóa trên
DataTable.

II.6.8. Tìm DataRow có khóa chính chứa trị truyền vào


Cú pháp:

<DataTable>.Rows.Find(<trị>)

Phương thức trả về dòng chứa <trị> trên cột khóa chính. Nếu không tìm thấy trả về Nothing

<DataTable>.Rows.Find(<mảng trị>)

Phương thức trả về DataRow chứa bộ giá trị <mảng trị> trên các cột khóa chính. Thứ tự trị truyền vào
phải theo thứ tự các cột khóa trên DataTable.

II.6.9. Minh họa tạo thao tác với tập hợp Rows
Ví dụ sau đây sẽ sử dụng cấu trúc của DataTable PHONGBAN, NHANVIEN phần trên và thêm vào các
mẩu tin.

Ví dụ:

bang_phong.Rows.Add(New Object(){"HC", "Hành chánh"})


bang_phong.Rows.Add(New Object(){"TC", "Tổ chức"})
Dim dong As DataRow = bang_nhan_vien.NewRow()
dong(0)= "A001"
dong(1)= "Nguyễn Văn"
dong(2)= "Ba"
dong(3)= True
dong(4)= #12/10/1980#
dong(5)= 1.25
dong(6)= "HC"
bang_nhan_vien.Rows.Add(dong)
bang_nhan_vien.Rows.Add(New Object(){"A002", "Trần Công", "Minh", True, _
"25/04/1977", 1.75, "TC"})
Dim nv() As Object = New Object(){"A003", "Lê Thị Kim", "Hương", False, _

Học phần 3 – VB.NET Trang 123/187


Tài liệu hướng dẫn giảng dạy

"05/09/1982", 1.25, "HC"}


bang_nhan_vien.Rows.Add(nv)
' Tìm nhân viên có mã là “A001”, nếu tìm thấy hủy nhân viên đó
If bang_nhan_vien.Rows.Contains(“A001”) then
Dim dg As DataRow = bang_nhan_vien.Rows.Find(“A001”)
' Để đánh dấu hủy
dg.Delete()
' Nếu muốn loại bỏ hẳn khỏi DataTable
' bang_nhan_vien.Rows.Remove(dg)
End If

II.7. Tập hợp Constraints


Minh họa tạo thao tác với tập hợp Constraints

Ví dụ: Sử dụng cấu trúc của DataTable PHONGBAN, NHANVIEN ở trên

' tạo ràng buộc duy nhất là khóa chính cho DataTable PHONGBAN
bang_phong.Constraints.Add("Khoa", bang_phong.Columns("Mapb"), True)
' tạo một ràng buộc duy nhất trên cột Manv của DataTable NHANVIEN
Dim khoa_duy_nhat As New UniqueConstraint( bang_nhan_vien.Columns("Manv"))
' tạo ràng buộc khóa ngoại trên cột Mapb của PHONGBAN và Mapb của NHANVIEN
Dim khoa_ngoai as New ForeignKeyConstraint(bang_phong.Columns(“Mapb”), _
bang_nhan_vien.Columns("Mapb"))
' Đưa hai ràng buộc vừa tạo vào tập hợp Constraints
bang_nhan_vien.Constraints.Add(khoa_duy_nhat)
bang_nhan_vien.Constraints.Add(khoa_ngoai)

II.8. Một số phương thức của DataTable


II.8.1. Để phát sinh một dòng mới có cấu trúc của DataTable
Cú pháp:

<DataTable>.NewRow()

Phương thức này trả về một DataRow mới có cấu trúc như của DataTable với các giá trị mặc định
nhưng chưa đưa vào tập hợp Rows (nghĩa là chưa thuộc về DataTable, có trạng thái là Detached). Và
một khi được đưa vào tập hợp sẽ có trạng thái là Added.

II.8.2. Hủy tất cả các dòng dữ liệu trên DataTable


Cú pháp:

<DataTable>.Clear()

II.8.3. Sao chép cấu trúc, ràng buộc của DataTable thành DataTable khác
Cú pháp:

Học phần 3 – VB.NET Trang 124/187


Tài liệu hướng dẫn giảng dạy

<DataTable>.Clone()

Phương thức trả về một DataTable đã có sẵn cấu trúc và ràng buộc của DataTable nhưng không có dữ
liệu

II.8.4. Sao chép cấu trúc, ràng buộc và dữ liệu của DataTable thành DataTable khác
Cú pháp:

<DataTable>.Copy()

Phương thức trả về một DataTable đã có sẵn cấu trúc, ràng buộc và dữ liệu của DataTable. DataTable
trả về có cùng cấp với DataTable - nếu DataTable là đối tượng của một lớp kế thừa, DataTable trả về
cũng thuộc lớp đó.

II.8.5. Để lấy ra một bản sao những thay đổi trên DataTable
Cú pháp:

<DataTable>.GetChanges()

Phương thức trả về một DataTable gồm những dòng dữ liệu đã thay đổi kể từ lần lấy dữ liệu từ nguồn
về hoặc từ lần cập nhật trước vào DataTable bằng Phương thức AcceptChanges.

<DataTable>.GetChanges(<trạng thái DataRow>)

Như trên nhưng chỉ trả về những dòng có tình trạng đúng với <trạng thái DataRow>.

II.8.6. Lấy ra một mảng các dòng bị lỗi trên DataTable


Cú pháp:

<DataTable>.GetErrors()

Phương thức trả về một mảng các DataRow bị lỗi. Phương thức này được gọi sau khi gọi GetChanges
nhằm phát hiện các dòng bị lỗi để xử lý.

II.8.7. Cập nhật các thay đổi vào DataTable


Cú pháp:

<DataTable>.AcceptChanges()

Phương thức cập nhật các thay đổi kể từ lần cập nhật trước hoặc khi DataTable được mở vào chính nó.
Sau khi thực hiện tất cả các DataRow đều có trạng thái Unchanged. Những DataRow có trạng thái
Deleted bị loại bỏ khỏi DataTable.

II.8.8. Hủy bỏ các thay đổi của DataTable


Cú pháp:

<DataTable>.RejeptChanges()

Phương thức phục hồi lại các giá trị kể từ lần cập nhật trước hoặc khi DataTable được mở vào chính
DataTable. Sau khi thực hiện, tất cả các dòng mới thêm vào đều bị loại bỏ. Những DataRow có trạng
thái Deleted, Modified được phục hồi lại tình trạng gốc.

Học phần 3 – VB.NET Trang 125/187


Tài liệu hướng dẫn giảng dạy

II.8.9. Tính toán trên các DataRow của DataTable


Cú pháp:

<DataTable>.Compute(<biểu thức tính toán>,<biểu thức lọc>)

Phương thức thực hiện tính toán theo <biểu thức tính toán> trên những dòng thỏa điều kiện của <biểu
thức lọc> và trả về giá trị tính toán được kiểu Object.
Trong <biểu thức tính toán>, phải có hàm thống kê (Count, Sum,…)
<biểu thức lọc> : phải có dạng <tên cột> <toán tử> <giá trị>
Ví dụ: Dựa DataTable NHANVIEN ở trên, để đếm các nhân viên nữ thuộc phòng Hành chánh

Dim sonvNu = dt.Compute("Count(Manv)", "Phai = False And Mapb = 'HC'")

II.8.10. Chọn các DataRow của DataTable


Cú pháp:

<DataTable>.Select()

Phương thức trả về mảng các DataRow trên DataTable theo thứ tự của khóa chính nếu có.

Select(<biểu thức lọc>)

Phương thức trả về mảng các DataRow trên DataTable thỏa điều kiện của <biểu thức lọc> theo thứ tự
của khóa chính nếu có.

Select(<biểu thức lọc>, <biểu thức sắp xếp>)

Phương thức trả về mảng các DataRow trên DataTable thỏa điều kiện của <biểu thức lọc> theo thứ tự
của <biểu thức sắp xếp>.

Select(<biểu thức lọc>, <biểu thức sắp xếp>,<trạng thái dòng>)

Phương thức trả về mảng các DataRow trên DataTable thỏa điều kiện của <biểu thức lọc> theo thứ tự
của <biểu thức sắp xếp> và có RowState ứng với tham số <trạng thái dòng>.
Ví dụ: Dựa DataTable NHANVIEN ở trên, chọn ra các nhân viên thuộc phòng Hành chánh

Dim dong() As DataRow = bang_nhan_vien.Select("Mapb = 'HC'")

Chọn và sắp xếp

Dim dong() As DataRow = bang_nhan_vien.Select("Mapb = 'HC'", _


"ngaysinh DESC")

II.9. Các sự kiện của DataTable


Các sự kiện

Tên Mô tả
ColumnChanged Sự kiện xảy ra sau khi giá trị trên cột của một dòng đã thay đổi.
Tham số EventArgs chứa thông tin:
ƒ Column: DataColumn thay đổi
ƒ ProposedValue: giá trị thay đổi của DataColumn

Học phần 3 – VB.NET Trang 126/187


Tài liệu hướng dẫn giảng dạy

ƒ Row: DataRow có cột thay đổi

ColumnChanging Sự kiện xảy ra khi giá trị trên cột của một DataRow đang thay đổi. Tham số
EventArgs chứa thông tin như ColumnChanged
RowChanged Sự kiện xảy ra sau khi một DataRow đã thay đổi thành công (không phát
sinh Exception)
Tham số EventArgs chứa thông tin:
ƒ Action: hành động đã xảy ra trên dòng
ƒ Row: dòng có hành động xảy ra

RowChanging Sự kiện xảy ra khi một dòng đang thay đổi. Tham số EventArgs chứa thông
tin như RowChanged
RowDeleted Sự kiện xảy ra sau khi một dòng trên DataTable đã bị đánh dấu hủy. Tham
số EventArgs chứa thông tin như RowChanged
RowDeleting Sự kiện xảy ra trước khi một dòng trên DataTable bị đánh dấu hủy. Tham số
EventArgs chứa thông tin như RowChanged

III. DataRelation
DataSet quản lý quan hệ giữa các DataTable trong DataSet qua tập hợp Relations. Đây là những đối
tượng DataRelation chứa thông tin về mối quan hệ đã tạo ra trong DataSet.
Quan hệ giữa hai DataTable nói lên sự liên quan của một dòng (DataRow) trên DataTable cha với các
DataRow trên DataTable con. Do đó, chúng ta có thể thấy được mối quan hệ đó qua việc hiển thị dữ
liệu các dòng tương ứng trên DataTable con (một cách tự động qua việc liên kết lưới DataTable con với
quan hệ đã tạo) khi dòng hiện hành trên DataTable cha thay đổi.
Ràng buộc, ngược lại, nhằm bảo vệ tính toàn vẹn dữ liệu thông qua mối quan hệ sẽ kiểm tra sự tồn tại
của DataRow bên DataTable cha khi thêm, sửa trên DataTable con hoặc kiểm tra tồn tại các dòng con
khi hủy trên DataTable cha
DataRelation thuộc tên lớp System.Data.DataRelation

III.1. Khởi tạo


Ngoài cách tạo quan hệ qua tập hợp Relations của DataSet đã đề cập ở phần trước, còn có các cách
khởi tạo sau:

Cú pháp:

New DataRelation(<tên>, <cột DataTable cha>, <cột DataTable con>)


New DataRelation(<tên>, <mảng cột DataTable cha>, _
<mảng cột DataTable con>)
New DataRelation(<tên>, <cột DataTable cha>, <cột DataTable con>, _
<tạo ràng buộc>)
New DataRelation(<tên>, <mảng cột DataTable cha>, _
<mảng cột DataTable con>, <tạo ràng buộc>)

<tạo ràng buộc>: Có giá trị True/False cho biết khi thiết lập quan hệ sẽ tạo luôn các ràng buộc hay

Học phần 3 – VB.NET Trang 127/187


Tài liệu hướng dẫn giảng dạy

không (xem phần tạo DataRelation giữa 2 DataTable trên DataSet)


Kinh nghiệm giảng dạy:
Chỉ có thể thiết lập quan hệ giữa hai DataTable chỉ khi hai DataTable đó thuộc về một
DataSet

III.2. Các thuộc tính của DataRelation


Các thuộc tính
Tên Mô tả
ChildColumns Trả về các DataColumn trên DataTable con tham gia trong DataRelation.
ChildKeyConstraint Trả về ràng buộc khóa ngoại của DataRelation.
ChildTable Trả về DataTable con trong DataRelation.
DataSet Trả về DataSet chứa DataRelation.
ParentColumns Trả về các cột trên DataTable cha tham gia trong DataRelation.
ParentKeyConstraint Trả về ràng buộc duy nhất bảo đảm giá trị cột trên DataTable cha trong
DataRelation có trị duy nhất.
ParentTable Trả về DataTable cha trong DataRelation.
RelationName Tên DataRelation (đọc ghi)

III.3. Minh họa thiết lập quan hệ


Ví dụ sau đây sẽ sử dụng bang_phong_ban, bang_nhan_vien ở phần trên để thiết lập quan hệ giữa cột
Mapb của bang_phong_ban với Mapb của bang_nhan_vien.
Ví dụ: Dựa DataTable NHANVIEN ở trên, chọn ra các nhân viên thuộc phòng Hành chánh
Đưa hai bảng vào một DataSet:

Dim dst As New DataSet()


dst.Tables.AddRange(New DataTable(){bang_phong,bang_nhan_vien})

Sau đó, có thể sử dụng một trong các cách sau:

Dim rel As New DataRelation("PB_NV", bang_phong.Columns("Mapb"), _


bang_nhan_vien.Columns(“Mapb”))
dst.Relations.Add(rel)

Hoặc:

dst.Relations.Add("PB_NV", bang_phong.Columns("Mapb"), _
bang_nhan_vien.Columns(“Mapb”))

Hoặc:

bang_phong.ChildRelations.Add("PB_NV", bang_phong.Columns("Mapb"), _
bang_nhan_vien.Columns(“Mapb”))

Hoặc:

bang_nhan_vien.ParentRelations.Add("PB_NV", bang_phong.Columns("Mapb"), _

Học phần 3 – VB.NET Trang 128/187


Tài liệu hướng dẫn giảng dạy

bang_nhan_vien.Columns(“Mapb”))

IV. DataView
Trong các đối tượng chúng ta đã tìm hiểu, vẫn còn thiếu một số chức năng như tìm kiếm với ý nghĩa
định vị trí, sắp xếp, lọc dữ liệu…ADO.Net đưa ra DataView như một đối tượng thuận tiện cho việc liên
kết dữ liệu với các điều khiển, sắp xếp…nhằm bổ sung cho những yêu cầu trên và cung cấp cho chúng
ta một cách hiển thị dữ liệu tùy biến của DataTable.
Với chức năng hiển thị dữ liệu tùy biến, DataView cho phép hiển thị dữ liệu của một DataTable qua các
điều khiển khác nhau với các số liệu khác nhau như dùng một điều khiển hiển thị tất cả các dòng dữ
liệu trên DataTable và một điều khiển khác hiển thị dữ liệu của những dòng đã bị đánh dấu hủy cũng
của DataTable đó …
Mặc định mỗi DataTable có sẵn một DataView thông qua thuộc tính DefaultView.
DataView thuộc tên lớp System.Data.DataView

IV.1. Khởi tạo


Cú pháp:

New DataView()

Tạo một đối tượng DataView mới

New DataView(<DataTable>)

Tạo một đối tượng DataView mới từ <DataTable>

New DataView(<DataTable>,<biểu thức lọc>, <biểu thức sắp xếp>, _


<trạng thái dòng>)

Tạo một DataView mới từ <DataTable> gồm những dòng thoả điều kiện <biểu thức lọc> và có tình
trạng như <trạng thái dòng>, được hiển thị theo cách sắp xếp <biểu thức sắp xếp>

IV.2. Các thuộc tính chính của DataView


Các thuộc tính
Tên Mô tả
AllowDelete Giá trị cho biết thao tác xóa dòng trên DataView có được phép không (đọc
ghi).
AllowEdit Giá trị cho biết thao tác sửa đổi trên DataView có được phép không (đọc
ghi).
AllowNew Giá trị cho biết thao tác thêm mới với Phương thức AddNew trên DataView có
được phép không (đọc ghi).
Count Số mẩu tin trên DataView sau khi áp dụng thuộc tính RowFilter và
RowStateFilter.
Item Trả về một dòng dữ liệu trên bảng theo tham số truyền vào.
RowFilter Biểu thức lọc của DataView để thay đổi dữ liệu hiển thị.
RowStateFilter Giá trị cho biết trạng thái dòng dữ liệu đang hiển thị trên DataView gồm các

Học phần 3 – VB.NET Trang 129/187


Tài liệu hướng dẫn giảng dạy

trị sau:
ƒ Added: Dòng mới thêm vào chưa cập nhật.
ƒ CurrentRows: Dòng hiện hành bao gồm những dòng không thay đổi,
dòng mới và dòng đã thay đổi.
ƒ Deleted: Dòng đánh dấu hủy.
ƒ ModifiedCurrent: Dòng đã được thay đổi và giá trị hiển thị là phiên
bản hiện hành, tức phiên bản đã sửa đổi từ dữ liệu gốc.
ƒ ModifiedOriginal: Dòng đã được thay đổi và giá trị hiển thị là phiên
bản gốc.
ƒ None: Không gì cả.
ƒ OriginalRows: Dòng gốc bao gồm các dòng không thay đổi và dòng
đã đánh dấu hủy.
ƒ Unchanged: Dòng không thay đổi.

Sort Tên cột hoặc các cột của DataTable dùng sắp xếp dữ liệu trên Dataview ngăn
cách nhau bằng dấu phẩy (đọc ghi). Nếu sắp xếp tăng không ghi thêm gì
hoặc "ASC", sắp xếp giảm thêm "DESC"
Table DataTable (đọc ghi) mà DataView đang lấy dữ liệu

IV.3. Các thao tác chính của DataView


IV.3.1. Thêm một dòng mới trên DataView
Cú pháp:

<DataView>.Add()

Phương thức trả về một DataRowView (sẽ đề cập đến phần sau).

IV.3.2. Đánh dấu hủy một dòng trên DataView


Cú pháp:

<DataView>.Delete(<chỉ số>)

Phương thức thực hiện đánh dấu hủy dòng trên DataView có chỉ số truyền vào. Sau khi thực hiện, dòng
có trạng thái là Deleted và có thể phục hồi bằng RejectChanges.

IV.3.3. Tìm kiếm trên DataView


Cú pháp:

<DataView>.Find(<giá trị>)

Phương thức thực hiện tìm kiếm <giá trị> trên DataView và trả về chỉ số của dòng đầu tiên thỏa giá trị
tìm. DataView phải được sắp xếp trên cột muốn tìm kiếm.

<DataView>.Find(<mảng giá trị>)

Phương thức thực hiện tìm kiếm <mảng giá trị> trên các cột tương ứng của DataView và trả về chỉ số
của dòng đầu tiên thỏa giá trị tìm. DataView phải được sắp xếp trên các cột có trị muốn tìm kiếm.

Nếu tìm thấy, phương thức trả về chỉ số dòng tìm thấy, ngược lại không tìm thấy trả về -1

Học phần 3 – VB.NET Trang 130/187


Tài liệu hướng dẫn giảng dạy

<DataView>.FindRows(<giá trị>)
Phương thức thực hiện tìm kiếm <giá trị> trên DataView và trả về những dòng thỏa giá trị tìm.
DatView phải được sắp xếp trên cột muốn tìm kiếm.
<DataView>.FindRows(<mảng giá trị>)

Phương thức thực hiện tìm kiếm <mảng giá trị> trên các cột tương ứng của DataView và trả về những
dòng thỏa giá trị tìm. DataView phải được sắp xếp trên các cột có trị muốn tìm kiếm.
Nếu tìm thấy, phương thức trả về mảng các dòng thỏa điều kiện, ngược lại trả về mảng không có phần
tử nào
Ví dụ : Để tìm kiếm nhân viên có họ “Lê Công”, tên “Minh” trên bang_nhan_vien đề cập ở trên

Dim dv As DataView = bang_nhan_vien.DefaultView


dv.Sort = "Honv,Tennv"
Dim vitri as Integer = dv.Find(New Object(){"Lê Công", "Minh"})
If vitri > -1 then
Console.WriteLine("Tìm thấy tại dòng thứ {0}", vitri )
Else
Console.WriteLine("Không tìm thấy")
End If

IV.4. DataRowView
Tương tự DataRow trên DataTable, DataRowView là một cách hiển thị của DataRow theo phiên bản
(xin xem phần dưới) trên DataView.
Khi liên kết với một điều khiển dữ liệu, chỉ có một phiên bản của DataRowView được hiển thị. Các phiên
bản đó là Default, Original, Current, và Proposed như của DataRow.
Chỉ có thể tạo DataRowView bằng phương thức AddNew của DataView

IV.4.1. Các thuộc tính của DataRowView


Các thuộc tính
Tên Mô tả
DataView Trả về DataView chứa DataRowView.
IsEdit Cho biết dòng có đang ở trong trạng thái chỉnh sửa.
IsNew Cho biết dòng có phải là dòng mới thêm vào.
Item Giá trị của dòng trên cột truyền vào dưới hình thức tên cột hoặc chỉ số cột
Row Trả về DataRow tương ứng trên DataTable.
RowVersion Trả về phiên bản hiện hành trên dòng với các trị:
ƒ Default: Giá trị hiện hành là giá trị mặc định
ƒ Original: Giá trị hiện hành là giá trị gốc
ƒ Current: Giá trị trên dòng là giá trị hiện hành
ƒ Proposed: Giá trị trên dòng là giá trị đang chỉnh sửa.
Thuộc tính này cho biết giá trị hiện hành đang là giá trị của phiên bản nào.

Học phần 3 – VB.NET Trang 131/187


Tài liệu hướng dẫn giảng dạy

Các yếu tố sau giúp xác định phiên bản:


ƒ Sau khi phương thức BeginEdit được gọi, nếu chúng ta thay đổi giá trị
chỉ có thể có các phiên bản Current và Proposed.
ƒ Sau khi phương thức CancelEdit được gọi, không còn giá trị Proposed.
ƒ Sau khi phương thức EndEdit được gọi, giá trị Proposed trở thành giá
trị Current.
ƒ Sau khi phương thức AcceptChanges được gọi, giá trị Current trở
thành giá trị Original.

IV.4.2. Các phương thức của DataRowView


Các phương thức
Tên Mô tả
BeginEdit Bắt đầu giai đoạn chỉnh sửa trên dòng. Sau khi giá trị thay đổi, để truy xuất
giá trị mới, chúng ta phải tham chiếu qua RowVersion là
DataRowVersion.Proposed
CancelEdit Sau khi phương thức BeginEdit được gọi, những thay đổi trên DataRowView
có thể hủy bỏ bằng phương thức CancelEdit.
CreateChildView Trả về một DataView gồm những dòng trên DataTable con thông qua
DataRelation ứng với DataRowView . Có các cú pháp sau :
<DataRowView>.CreateChildView(<DataRelation>)
<DataRowView>.CreateChildView(<tên DataRelation>)

Delete Đánh dấu hủy bỏ dòng. Dòng chưa thực sự bị hủy cho đến khi phương thức
AcceptChanges của bảng được gọi.
EndEdit Chấm dứt giai đoạn chỉnh sửa và cập nhật các thay đổi trên dòng.

Học phần 3 – VB.NET Trang 132/187


Tài liệu hướng dẫn giảng dạy

Bài 7
XÂY DỰNG CÁC LỚP XỬ LÝ
Tóm tắt
Lý thuyết 3 tiết - Thực hành 10 tiết

Mục tiêu Các mục chính Bài tập

Kết thúc bài học này, học viên có thể 1. Mô hình đa tầng 5.3, 5.4, 5.5
xây dựng các lớp xử lý sử dụng trong 2. Xây dựng lớp xử lý lưu trữ
mô hình lập trình dữ liệu
3. Xây dựng lớp xử lý nghiệp vụ

Học phần 3 – VB.NET Trang 133/187


Tài liệu hướng dẫn giảng dạy

I. Mô hình đa tầng (N-tier)

Người

Xử lý thể hiện

Xử lý nghiệp vụ

Xử lý lưu trữ

Dữ liệu

Trong mô hình này, ứng dụng được phân chia thành nhiều tầng với các chức năng khác nhau:
– Tầng xử lý thể hiện có chức năng hiển thị thông tin ra màn hình giao tiếp và tiếp nhận thông tin từ
người dùng
– Tầng xử lý nghiệp vụ cung cấp và xử lý thông tin của dữ liệu từ hai tầng kế cận (thể hiện và lưu
trữ)
– Tầng xử lý lưu trữ có chức năng truy xuất và cập nhật thông tin vào nguồn dữ liệu (đọc/ghi)
Vì tính độc lập của các tầng, mô hình này thích hợp cho việc xây dựng ứng dụng khi thay đổi nguồn dữ
liệu, môi trường lập trình, … và tận dụng được khả năng tái sử dụng.

Có nhiều hình thức xây dựng lớp cho mỗi tầng, nhưng trong phạm vi giáo trình này, chúng tôi sẽ sử
dụng nguyên tắc kế thừa nhằm thuận lợi cho học viên trong khi triển khai

II. Xây dựng lớp xử lý lưu trữ


Đây là lớp làm việc trực tiếp với nguồn dữ liệu. Với vai trò đọc dữ liệu về cho ứng dụng cũng như cập
nhật các thay đổi từ phía người dùng vào nguồn dữ liệu, lớp sẽ có các thuộc tính, chức năng hổ trợ cho
các vai trò này. Khi tạo lớp, cần thực hiện:
– Phân chia các Region để tiện việc quản lý các thuộc tính, sự kiện và phương thức
– Truy xuất dữ liệu của bảng được thực hiện thông qua DefaultView của DataTable

Học phần 3 – VB.NET Trang 134/187


Tài liệu hướng dẫn giảng dạy

II.1. Các khai báo


Đây là nhóm khai báo các biến thành viên, hằng cần sử dụng bên trong lớp và thường được khai báo
với từ khóa Private:
– Khai báo đối tượng truy xuất cập nhật dữ liệu(DataAdapter): đối tượng này đóng vai trò đọc ghi dữ
liệu cho lớp xử lý lưu trữ
– Biến chuỗi chứa nội dung truy vấn dữ liệu
– Biến chuỗi chứa tên bảng muốn truy vấn dữ liệu
– Biến đối tượng dùng chung kết nối đến nguồn dữ liệu.
Ví dụ:

Imports System.Data
Imports System.Data.OleDb

Module PHAN_MEM
Public Const Chuoi_lien_ket As String = _
"Provider=Microsoft.JET.OLEDB.4.0;"
End Module

Public Class XL_BANG


Inherits DataTable

#Region "Khai báo cục bộ "


' Khai báo đối tượng đọc ghi dữ liệu trên CSDL
Private WithEvents mBo_doc_ghi As OleDbDataAdapter
' Khai báo biến chuỗi chứa nội dung truy vấn dữ liệu
Private mChuoi_SQL As String
' Khai báo biến chuỗi chứa tên bảng muốn truy vấn dữ liệu
Private mTen_bang As String
' Khai báo biến đối tượng dùng chung kết nối đến nguồn dữ liệu
Private Shared mKet_noi As OleDbConnection
#End Region
. . .
End Class

II.2. Khai báo các thuộc tính


Đây là phần khai báo các thuộc tính của lớp xử lý lưu trữ cho phép truy xuất từ bên ngoài lớp thường
được khai báo với từ khóa Public:
Ví dụ: XL_BANG: phần khai báo các thuộc tính

#Region " Khai báo các thuộc tính "


' Giá trị của thuộc tính này cần được khởi tạo trước khi sử dụng

Học phần 3 – VB.NET Trang 135/187


Tài liệu hướng dẫn giảng dạy

Public Shared Chuoi_CSDL As String

' Thuộc tính cho phép đọc và ghi nội dung truy vấn dữ liệu cần thực hiện
cho thể hiện
Public Property Chuoi_SQL() As String
Get
Return mChuoi_SQL
End Get
Set(ByVal Value As String)
mChuoi_SQL = Value
End Set
End Property

' Thuộc tính cho phép truy xuất và gán tên bảng muốn truy vấn dữ liệu
Public Property Ten_bang() As String
Get
Return mTen_bang
End Get
Set(ByVal Value As String)
mTen_bang = Value
End Set
End Property

' Thuộc tính chứa đối tượng kết nối đến nguồn dữ liệu
Public Shared Property Ket_noi() As OleDbConnection
Get
Return mKet_noi
End Get
Set(ByVal Value As OleDbConnection)
mKet_noi = Value
End Set
End Property

' Thuộc tính chỉ đọc cho biết số dòng trên DefaultView của DataTable
Public ReadOnly Property So_dong() As Long
Get
Return Me.DefaultView.Count
End Get
End Property
#End Region

Học phần 3 – VB.NET Trang 136/187


Tài liệu hướng dẫn giảng dạy

II.3. Khai báo phương thức khởi tạo


Nhóm gồm những hàm khởi tạo đối tượng chứa dữ liệu, đồng thời khởi tạo các đối tượng thực hiện đọc
ghi dữ liệu:

Ví dụ: XL_BANG: phần khai báo các hàm khỏi tạo

#Region " Khai báo phương thức khởi tạo "


' Thủ tục khởi tạo một thể hiện DataTable chưa có cấu trúc và dữ liệu
Public Sub New()
MyBase.New()
End Sub

' Thủ tục khởi tạo đọc toàn bộ bảng


Public Sub New(ByVal pTen_bang As String)
MyBase.New(pTen_bang)
mTen_bang = pTen_bang
Doc_bang()
End Sub

' Thủ tục khởi tạo đọc bảng theo nội dung yêu cầu
Public Sub New(ByVal pTen_bang As String, ByVal pChuoi_SQL As String)
MyBase.New(pTen_bang)
mTen_bang = pTen_bang
mChuoi_SQL = pChuoi_SQL
Doc_bang()
End Sub
#End Region

II.4. Khai báo phương thức xử lý - cung cấp thông tin


Nhóm gồm những chức năng xử lý và cung cấp thông tin:
Ví dụ: XL_BANG: phần khai báo các phương thức xử lý – cung cấp thông tin

#Region " Khai báo phương thức xử lý – cung cấp thông tin "
' Thủ tục khởi tạo đối tượng đọc ghi dữ liệu và khai báo thông tin cho đối
tượpng kết nối
' Thực hiện lấy cấu trúc và dữ liệu vào DataTable. Sau cùng phát sinh các
lệnh cập nhật
Private Sub Doc_bang()
If mChuoi_SQL = "" Then mChuoi_SQL = "SELECT * FROM " & mTen_bang
If mKet_noi Is Nothing Then
mKet_noi = New OleDbConnection
mKet_noi.ConnectionString = Chuoi_lien_ket & "Data Source=" &
Chuoi_CSDL

Học phần 3 – VB.NET Trang 137/187


Tài liệu hướng dẫn giảng dạy

End If
Try
mBo_doc_ghi = New OleDbDataAdapter(mChuoi_SQL, mKet_noi)
mBo_doc_ghi.Fill(Me)
mBo_doc_ghi.FillSchema(Me, SchemaType.Mapped)
mBo_doc_ghi.SelectCommand.CommandText = "Select * FROM " &
mTen_bang
Dim Bo_phat_sinh As New OleDbCommandBuilder(mBo_doc_ghi)
Catch ex As OleDbException
End Try
End Sub

' Hàm cập nhật các thay đổi trên DataTable vào CSDL và cập nhật các dòng
trên DataTable
' về trạng thái không thay đổi. Nếu cập nhật được, hàm trả về True; ngược
lại, bỏ qua các
' thay đổi và trả về False
Public Function Ghi() As Boolean
Dim ketqua As Boolean = True
Try
mBo_doc_ghi.Update(Me)
Me.AcceptChanges()
Catch e As Exception
Me.RejectChanges()
ketqua = False
End Try
Return ketqua
End Function

' Thủ tục lọc dữ liệu của DefaultView theo điều kiện lọc truyền vào
Public Sub Loc_du_lieu(ByVal pDieu_kien As String)
Try
Me.DefaultView.RowFilter = pDieu_kien
Catch ex As Exception
End Try
End Sub
#End Region

Học phần 3 – VB.NET Trang 138/187


Tài liệu hướng dẫn giảng dạy

II.5. Khai báo các phương thức thực hiện lệnh


Nhóm gồm những hàm, thủ tục cung cập chức năng thực hiện lệnh:
Ví dụ: XL_BANG: Khai báo các phương thức thực hiện lệnh

#Region " Khai báo các phương thức thực hiện lệnh "

' Hàm thực hiện nội dung lệnh truyền vào và trả về số mẩu tin được cập
nhật, nếu thành
' công. Nếu không thành công, hàm trả về -1
Public Function Thuc_hien_lenh(ByVal Lenh As String) As Integer
Try
Dim Cau_lenh As New OleDbCommand(Lenh, mKet_noi)
mKet_noi.Open()
Dim ket_qua As Integer = Cau_lenh.ExecuteNonQuery()
mKet_noi.Close()
Return ket_qua
Catch ex As OleDbException
Return -1
End Try
End Function

' Hàm thực hiện nội dung lệnh tính toán thống kê truyền vào và trả về kết
quả, nếu thành
' công. Nếu không thành công, hàm trả về Nothing
Public Function Thuc_hien_lenh_tinh_toan(ByVal Lenh As String) As Object
Try
Dim Cau_lenh As New OleDbCommand(Lenh, mKet_noi)
mKet_noi.Open()
Dim ket_qua As Object = Cau_lenh.ExecuteScalar
mKet_noi.Close()
Return ket_qua
Catch ex As OleDbException
Return Nothing
End Try
End Function
#End Region

Học phần 3 – VB.NET Trang 139/187


Tài liệu hướng dẫn giảng dạy

II.6. Nhóm xử lý sự kiện


Ví dụ: XL_BANG: Xử lý sự kiện

#Region " Xử lý sự kiện "


' Khi khóa chính là cột tự động tăng, giá trị cột này được CSDL tự
' phát sinh nên cần truy xuất về để sử dụng cho việc cập nhật sau đó.
Private Sub mBo_doc_ghi_RowUpdated(ByVal sender As Object, ByVal e As _
System.Data.OleDb.OleDbRowUpdatedEventArgs) _
Handles mBo_doc_ghi.RowUpdated
If e.Status = UpdateStatus.Continue AndAlso _
e.StatementType = StatementType.Insert Then
'Lấy gía trị AutoNumber
If Me.PrimaryKey(0).AutoIncrement Then
Dim lenh As New OleDbCommand("Select @@IDENTITY", mKet_noi)
e.Row.Item(0) = lenh.ExecuteScalar()
e.Row.AcceptChanges()
End If
End If
End Sub
#End Region

III. Xây dựng lớp xử lý nghiệp vụ


Lớp xử lý nghiệp vụ gồm các thành phần của riêng lớp đó.
Với mỗi bảng trong CSDL, cần xây dựng một lớp xử lý tương ứng với các điểm cần lưu ý:
– Lớp kế thừa từ lớp XL_BANG
– Lớp có hàm khởi tạo và tìm kiếm thông tin

III.1. Khai báo phương thức khởi tạo


Nhóm này có các phương thức khởi tạo khác nhau.
Ví dụ: Lớp xử lý nghiệp vụ XL_DIEN_VIEN

Imports System.Data
Imports System.Data.OleDb
Public Class XL_DIEN_VIEN
Inherits XL_BANG
#Region " Khai báo phương thức khởi tạo "
' Khởi tạo toàn bộ danh sách diễn viên
Public Sub New()
MyBase.New("DIEN_VIEN", "Select * From DIEN_VIEN")
End Sub

Học phần 3 – VB.NET Trang 140/187


Tài liệu hướng dẫn giảng dạy

' Khởi tạo thông tin diễn viên theo khóa chính
Public Sub New(ByVal pMDV As Int32)
MyBase.New("DIEN_VIEN", "Select * From DIEN_VIEN Where MDV = " & pMDV)
End Sub
' Khởi tạo danh sách diễn viên theo điều kiện
Public Sub New(ByVal pChuoi_SQL As String)
MyBase.New("DIEN_VIEN", pChuoi_SQL)
End Sub
#End Region

End Class

III.2. Khai báo phương thức tìm kiếm thông tin


Dựa vào các yêu cầu tìm kiếm thông tin lập biểu thức lọc để xác định các dòng thoả điều kiện tìm:
Ví dụ: XL_DIEN_VIEN: Phương thức tìm kiếm thông tin

#Region " Khai báo phương thức xử lý tìm kiếm thông tin "
Public Sub Tim(ByVal pDong_dieu_kien As DataRow)
Dim chuoi_Dk As String = ""
Dim mang_Dk As New ArrayList
Dim so_Pt As Byte = 0
If Not IsDBNull(pDong_dieu_kien("Ho_ten_dv")) Then
mang_Dk.Add("Ho_ten_dv LIKE '" & _
pDong_dieu_kien("Ho_ten_dv") & "*'")
End If

'Tiếp theo cho những điều kiện khác …


If mang_Dk.Count > 0 Then
Dim i As Integer
For i = 0 To mang_Dk.Count - 1
If i = 0 Then
chuoi_Dk = mang_Dk(i)
Else
chuoi_Dk += " AND " + mang_Dk(i)
End If
Next
Loc_du_lieu(chuoi_Dk)
End If
End Sub
#End Region

Học phần 3 – VB.NET Trang 141/187


Tài liệu hướng dẫn giảng dạy

Bài 8
THIẾT KẾ CÁC MÀN HÌNH
Tóm tắt
Lý thuyết 6 tiết - Thực hành 15 tiết

Mục tiêu Các mục chính Bài tập

Bài học này giúp cho học viên thiết 4. Các điều khiển hiển thị dữ liệu 5.6, 5.7, 5.8, 5.9,
kế và cài đặt các dạng màn hình cơ 5. Màn hình đơn 5.10, 5.11, 5.12,
bản trong ứng dụng Visual Basic 5.14
6. Màn hình một nhiều
7. Màn hình lọc theo điều kiện Bài làm thêm: 5.13

8. Màn hình một nhiều nhiều


9. Một số kỹ thuật trong hiển thị dữ
liệu

Học phần 3 – VB.NET Trang 142/187


Tài liệu hướng dẫn giảng dạy

I. Các điều khiển hiển thị dữ liệu


Với mô hình liên kết dữ liệu (DataBinding) các thay đổi trên dữ liệu hay trên các điều khiển tự động
tương tác qua lại. Ngược lại, trong mô hình không liên kết, dữ liệu từ lớp xử lý sẽ được xuất ra các điều
khiển hiển thị trên màn hình. Các thay đổi trên điều khiển sẽ được kiểm tra trước khi nhập vào lớp xử
lý. Vì vậy, cần phải có những chức năng nhập xuất, kiểm tra dữ liệu, . . .:
Dưới đây là bảng liệt kê thuộc tính hiển thị dữ liệu của một số điều khiển thường dùng trên màn hình

I.1. Thuộc tính liên kết dữ liệu của điều khiển


Các điều khiển hiển thị dữ liệu

Điều khiển Thuộc tính liên kết dữ liệu


Label Text
TextBox Text
DomainUpdown Text
Checkbox Checked
RadioButton Checked
ComboBox SelectedValue
ListBox SelectedValue
CheckListbox SelectedValue
DateTimePicker Value
NumericUpdown Value

I.2. ComboBox, ListBox, CheckListBox


Sau đây chúng ta sẽ đề cập đến một số điều khiển đặc biệt trong việc hiển thị dữ liệu.
Khi được dùng để hiển thị dữ liệu, chúng ta cần quan tâm đến các thuộc tính sau :
ƒ DataSource: Chỉ ra nguồn dữ liệu để lấy giá trị liệt kê chọn lựa
ƒ DisplayMember: Cho biết tên cột trên nguồn dữ liệu liệt kê sẽ được hiển thị trên điều khiển
ƒ ValueMember: Cho biết tên cột trên nguồn dữ liệu liệt kê sẽ được lấy giá trị để cập nhật vào
nguồn dữ liệu khi chọn một dòng trên điều khiển
ƒ SelectedValue: Giá trị của dòng được chọn ứng với cột có tên là giá trị của ValueMember.
Sự kiện cần lưu ý trên các điều khiển nầy:

Các sự kiện
Tên Mô tả
SelectedIndexChanged Xảy ra khi thuộc tính SelectedIndex thay đổi (do lệnh và tương tác).
SelectedValueChanged Xảy ra khi thuộc tính SelectedValue thay đổi (do lệnh và tương tác).
SelectionChangeCommitted Xảy ra khi dòng chọn thay đổi và đã được cập nhật (do tương tác)

Học phần 3 – VB.NET Trang 143/187


Tài liệu hướng dẫn giảng dạy

I.3. DataGrid
DataGrid là điều khiển cho phép liên kết dữ liệu dạng bảng gồm các dòng và các cột. Đặc điểm của
DataGrid trong .NET là có thể liên kết với DataSet chứa nhiều bảng, quan hệ và có thể hiện thị từng bảng
dữ liệu theo từng quan hệ trên lưới. Lưới lúc này hiển thị như cây thư mục, chọn bảng nào lưới sẽ chuyển
sang liên kết dữ liệu của bảng đó và xuất hiện các nút di chuyển về bảng trước, v.v…

DataGrid với các cách liên kết dữ liệu

Các nút di chuyển


về bảng trước,
sau v.v…

I.3.1. Các thuộc tính của DataGrid


Các thuộc tính thường dùng
Tên Mô tả
AllowSorting Định trị cho biết lưới có cho phép sắp xếp khi nhấn phần tiêu đề cột
hay không.
AlternatingBackColor Màu dòng xen kẻ trên lưới. Mặc định màu trắng tức màu các dòng
không xen kẻ.
CaptionFont Kiểu chữ cho phần tiều đề lưới.
CaptionText Nội dung tiêu đề lưới.
CaptionVisible Định trị cho biết có hiển thị tiêu đề lưới hay không.
ColumnHeadersVisible Định trị cho biết có hiển thị tiều đề cột hay không.
ContextMenu Thực đơn ngữ cảnh cho điều khiển.
Controls Trả về tập hợp các điều khiển trên lưới.
CurrentCell Ô hiện hành trên lưới. Không sử dụng được ở chế độ thiết kế.
CurrentRowIndex Chỉ số dòng hiện hành
DataMember Thành phần nhánh dữ liệu hiển thị trên lưới
DataSource Nguồn dữ liệu của lưới.
Enabled Định trị cho biết lưới sáng hay mờ.

Học phần 3 – VB.NET Trang 144/187


Tài liệu hướng dẫn giảng dạy

Font Kiểu chữ dùng hiện thị dữ liệu trên lưới


HeaderFont Kiểu chữ dùng hiện thị tiều đề cột trên lưới
Item Trị của ô có chỉ số truyền vào: Item(<dòng>,<cột>)
Name Tên điều khiển.
PreferredColumnWidth Độ rộng mặc định mỗi cột trên lưới theo đơn vị pixels.
PreferredRowHeight Chiều cao mặc định của mỗi dòng trên lưới.
ReadOnly Định trị cho biết lưới ở chế độ chỉ đọc hay không.
RowHeadersVisible Định trị cho biết có hiển thị tiều đề dòng hay không.
RowHeaderWidth Độ rộng của tiều đề dòng.
TableStyles Tập hợp các kiểu DataGridTableStyle của lưới.
Text Nội dung trên ô hiện hành
VisibleColumnCount Trả về số cột nhìn thấy trên lưới.
VisibleRowCount Trả về số dòng nhìn thấy trên lưới.

I.3.2. Các phương thức của DataGrid


Các phương thức thường dùng
Tên Mô tả
HitTest Lấy thông tin của lưới tại một vị trí chỉ ra trên màn hình. Cú pháp
HitTest (<hoành độ>,<tung độ>)
Phương thức trả về một đối tượng HitTestInfo của DataGrid cho biết
các thông tin về vùng được nhấn. Chúng ta có thể gọi phương thức này
trong sự kiện MouseDown để xác định dòng cột tại vị trí nhấn chuột…
thông qua HitTestInfo
IsSelected Trị cho biết dòng truyền vào có được chọn hay không.
IsSelected(<chỉ số dòng>)

SetDataBinding Liên kết dữ liệu với lưới thông qua DataSource và DataMember.
SetDataBinding(<datasource>, <datamember>)

Select Chọn dòng chỉ ra qua chỉ số truyền vào.


Select(<chỉ số dòng>)

UnSelect Bỏ chọn dòng chỉ ra qua chỉ số truyền vào.


UnSelect(<chỉ số dòng>)

I.3.3. Các sự kiện của DataGrid


Các sự kiện
Tên Mô tả
CurrentCellChanged Sự kiện xảy ra khi ô hiện hành thay đổi
MouseDown Sự kiện xảy ra khi nhấn chuột trên DataGrid

Học phần 3 – VB.NET Trang 145/187


Tài liệu hướng dẫn giảng dạy

I.4. DataGridTableStyle và TableStyles


I.4.1. DataGridTableStyle
DataGrid có tập hợp TableStyles gồm những DataGridTableStyle giúp chúng ta định dạng lưới theo một
yêu cầu hiển thị cụ thể tùy theo bảng dữ liệu. DataGridTableStyle thuộc không gian tên
System.Windows.Forms.DataGridTableStyle
Nếu DataView là nội dung cần hiển thị trên lưới thì DataGridTableStyle là hình thức phải tuân theo để
hiển thị.
Cú pháp: Khởi tạo một DataGridTableStyle

New DataGridTableStyle()

Các thuộc tính của DataGridTableStyle đều kế thừa của DataGrid nên bảng dưới chỉ trình bày các thuộc
tính mới và đáng chú ý:

Các thuộc tính của DataGridTableStyle


Tên Mô tả
DataGrid DataGrid mà DataGridTableStyle thuộc về.
GridColumnStyles Tập hợp các DataGridColumnStyle của DataGridTableStyle.
MappingName Tên dùng để ánh xạ đến một nguồn dữ liệu. Đây là tên của DataTable
muốn liên kết dữ liệu.

I.4.2. TableStyles
Do lưới có thể dùng hiển thị dữ liệu của các nguồn khác nhau nên chúng ta có thể tạo nhiều
DataGridTableStyle cho phù hợp với mỗi nguồn dữ liệu. Các DataGridTableStyle của lưới được tập hợp
lại thành TableStyles. Là một tập hợp (collection) nên TableStyles có các thuộc tính và phương thức
đặc trưng của tập hợp như Count, Item, Add, AddRange, Clear, Contains, Remove, RemoveAt. Cách sử
dụng các thuộc tính và phương thức của TableStyles cũng giống như cách đã trình bày trước đây về
các tập hợp khác.

I.5. DataGridColumnStyle và GridColumnStyles


I.5.1. DataGridColumnStyle
Trong khi DataGridTableStyle qui định cách hiển thị của nguồn dữ liệu của lưới thì DataGridColumnStyle
qui định cách hiển thị dữ liệu trên một cột. DataGridColumnStyle thuộc không gian tên
System.Windows.Forms.DataGridColumnStyle. Đây là lớp phải kế thừa (MustInherit). Hiện có hai lớp
phát sinh từ lớp này là:
ƒ System.Windows.Forms.DataGridBoolColumn
ƒ System.Windows.Forms.DataGridTextBoxColumn
Cú pháp: Khởi tạo một DataGridColumnStyle

New DataGridBoolColumn()
New DataGridTextBoxColumn()

Học phần 3 – VB.NET Trang 146/187


Tài liệu hướng dẫn giảng dạy

Các thuộc tính của DataGridColumnStyle


Tên Mô tả
Alignment Canh lề trong cột.
DataGridTableStyle Trả về DataGridTableStyle chứa cột.
HeaderText Tiêu đề của cột.
MappingName Tên cột trên bảng liên kết với cột.
NullText Nội dung hiển thị khi cột có trị Null.
ReadOnly Định trị cho biết có được phép chỉnh sửa dữ liệu trên cột hay không.
Width Độ rộng của cột.

Ngoài các thuộc tính chung nói trên, mỗi loại còn có các thuộc tính riêng của nó

Các thuộc tính riêng của DataGridBoolColumn


Tên Mô tả
AllowNull Trị cho biết cột có nhận giá trị Null hay không.
FalseValue Trị được sử dụng khi cột có giá trị False.
NullValue Trị được sử dụng khi cột có giá trị Null.
TrueValue Trị được sử dụng khi cột có giá trị True.

Các thuộc tính riêng của DataGridTextBoxColumn


Tên Mô tả
Format Biểu thức định dạng của cột
FormatInfo Đối tượng chứa thông tin định dạng theo văn hóa, quốc gia…
TextBox Trả về Textbox của cột

I.5.2. GridColumnStyles
GridColumnStyles là tập hợp các DataGridColumnStyle (cả DataGridBoolColumn lẫn
DataGridTextBoxColumn) của một DataGridTableStyle.

I.6. Thiết kế DataGrid


Khi DataGrid liên kết với nguồn dữ liệu, nếu chúng ta không tạo DataGridTableStyle qui định cách hiển
thị dữ liệu, lưới sẽ hiển thị dữ liệu theo định dạng mặc định của lưới. Để lưới hiển thị dữ liệu theo ý
muốn, chúng ta phải tạo DataGridTableStyle và các thành phần của nó.

I.6.1. Tạo DataGridTableStyle khi thiết kế (Design time)


Chúng ta tạo DataGridTableStyle và các DataGridColumnStyle theo
các bước sau :
ƒ Chọn thuộc tính TableStyle trên Properties và nhấn nút […]
ƒ Trên cửa sổ kế tiếp nhấn nút [Add] để tạo một
DataGridTableStyle mới, khai báo các thuộc tính cần thiết
như MappingName, ReadOnly,… và nhấn nút […] ở mục

Học phần 3 – VB.NET Trang 147/187


Tài liệu hướng dẫn giảng dạy

GridColumnStyles để tạo các DataGridColumnStyle.

Tạo DataGridTableStyle mới


ƒ Trên cửa sổ kế tiếp nhấn nút [d] bên phải nút [Add] để lựa chọn loại DataGridColumnStyle
muốn tạo, mặc định là DataGridTextBoxColumn :

Chọn loại DataGridColumnStyle


ƒ Nhấn nút [Add] để tạo một DataGridColumnStyle đã chọn và khai báo các thuộc tính cần thiết :
Alignment, HeaderText, Width, Format, MappingName, ReadOnly, NullText…Tiếp tục các cột
khác

Học phần 3 – VB.NET Trang 148/187


Tài liệu hướng dẫn giảng dạy

Tạo DataGridColumnStyle mới và khai báo

I.6.2. Tạo DataGridTableStyle lúc thực thi (Runtime)


Sử dụng lệnh tạo mới một DataGridTableStyle, kế tiếp tạo các DataGridColumnStyle và thêm vào
GridColumnStyles của DataGridTableStyle, sau cùng thêm DataGridTableStyle vừa tạo vào tập hợp
TableStyles của lưới.
Đoạn lệnh sau đây minh họa tạo DataGridTableStyle hiển thị dữ liệu bang_phong trên lưới
LUOI_PHONG.

Ví dụ:

Dim kieu_hien_thi_bang_phong As New DataGridTableStyle()


With kieu_hien_thi_bang_phong
.MappingName = bang_phong.TableName
Dim cot_ma_phong As New DataGridTextBoxColumn()
cot_ma_phong.MappingName = bang_phong.Columns(0).ColumnName
cot_ma_phong.HeaderText = “Mã PB”
cot_ma_phong.Width = 40
.GridColumnStyles.Add(cot_ma_phong)
Dim cot_ten_phong As New DataGridTextBoxColumn()
cot_ten_phong.MappingName = bang_phong.Columns(1).ColumnName
cot_ten_phong.HeaderText = “Tên phòng ban”
cot_ten_phong.Width = 150
.GridColumnStyles.Add(cot_ten_phong)
End With
LUOI_PHONG.TableStyles.Add(kieu_hien_thi_bang_phong)

Học phần 3 – VB.NET Trang 149/187


Tài liệu hướng dẫn giảng dạy


Kinh nghiệm giảng dạy:
Luôn luôn tạo các DataGridColumnStyle và thêm chúng vào GridColumnStyles của
DataGridTableStyle trước khi thêm DataGridTableStyle này vào TableStyles của lưới.
Khi thêm một DataGridTableStyle rỗng (chưa có các DataGridColumnStyle) vào
TableStyles, các DataGridColumnStyle sẽ được phát sinh tự động, vì thế khi chúng ta
thêm DataGridColumnStyle vào sẽ phát sinh lỗi do có các DataGridColumnStyle có
MappingName trùng nhau

I.7. Hiển thị dữ liệu ra điều khiển


Để hiển thị dữ liệu lên màn hình, chúng ta có thể xuất dữ liệu của lớp xử lý ra các điều khiển cần hiển
thị và khi cần cập nhật vào lớp xử lý lại thực hiện gán trị trên các điều khiển vào các cột tương ứng.
Phần dưới đây giới thiệu một số đối tượng liên quan đến việc đồng bộ dữ liệu trên màn hình

I.7.1. Dòng hiện hành


Như đã đề cập trong phần ADO.Net, dữ liệu trên DataTable hoặc trên DataView không có dòng hiện
hành như trong Recordset và tại mỗi thời điểm, có thể làm việc với bất kỳ dòng dữ liệu nào. Ngược lại
khi dữ liệu hiển thị trên màn hình, khái niệm hiện hành được đưa ra nhằm đồng bộ dữ liệu trên các
điều khiển cùng hiển thị thông tin của một nguồn dữ liệu.
Dưới đây giới thiệu các lớp đối tượng quản lý dữ liệu trên màn hình

I.7.2. BindingManagerBase
BindingManagerBase là đối tượng quản lý và cho phép đồng bộ dữ liệu các điều khiển trên màn hình
cùng liên kết đến cùng một đối tượng nguồn. Đây là một lớp trừu tượng. BindingManagerBase thuộc
không gian tên System.Windows.Forms.BindingManagerBase gồm hai lớp:
ƒ System.Windows.Forms.CurrencyManager
ƒ System.Windows.Forms.PropertyManager
CurrencyManager thực hiện việc đồng bộ bằng cách duy trì một con trỏ đến dòng hiện hành trên danh
sách. Các điều khiển liên kết đến dòng hiện hành sẽ hiển thị thông tin của cùng một dòng.
PropertyManager được dùng để duy trì thuộc tính hiện hành của đối tượng, đúng hơn là thuộc tính của
đối tượng hiện hành trên danh sách.

Cách tạo thường dùng nhất là từ đối tượng BindingContext của Form như sau:
Cú pháp: Khởi tạo một DataGridColumnStyle

Dim bm As BindingManagerBase = _
<form>.BindingContext(<nguồn dữ liệu>)

Hoặc:

Dim bm As BindingManagerBase = _
<form>.BindingContext(<nguồn dữ liệu>, <thành phần>)

Nếu nguồn dữ liệu là đối tượng chỉ trả về một thuộc tính, BindingContext sẽ trả về một
ProtertyManager. Ví dụ liên kết Text của Label với Text của Textbox.
Nếu nguồn dữ liệu là đối tượng chứa một danh sách, BindingContext sẽ trả về một CurrencyManager.
Ví dụ nguồn là DataSet, DataTable, DataView... một CurrencyManager được trả về.

Học phần 3 – VB.NET Trang 150/187


Tài liệu hướng dẫn giảng dạy

Các thuộc tính cần lưu ý của BindingManagerBase


Các thuộc tính cần chú ý của BindingManagerBase
Tên Mô tả
Count Số dòng trên danh sách do BindingManagerBase quản lý
Current Trả về đối tượng hiện hành (chỉ có tác dụng với CurrencyManager)
Position Vị trí của đối tượng hiện hành trên danh sách (đọc ghi, chỉ có tác dụng
với CurrencyManager).

Các phương thức cần chú ý của BindingManagerBase


Tên Mô tả
AddNew() Thêm dòng mới trên danh sách do BindingManagerBase quản lý. (như
AddNew của DataView). Dòng mới thêm được chuyển thành đối tượng
hiện hành (Current) trên BindingManagerBase
EndCurrentEdit() Chấm dứt chỉnh sửa trên đối tượng hiện hành và nếu là dòng mới sẽ
được đưa vào tập hợp Rows của DataTable (chỉ có tác dụng với
CurrencyManager)
CancelCurrentEdit() Bỏ qua các thay đổi của đối tượng hiện hành.

Các sự kiện của BindingManagerBase


Tên Mô tả
CurrentChanged Sự kiện xảy ra khi đối tượng hiện hành thay đổi
PositionChanged Sự kiện xảy ra khi vị trí hiện hành của BindingManagerBase thay đổi

I.7.3. BindingContext
Phát sinh từ lớp đối tượng System.Windows.Forms.BindingContext, BindingContext là đối tượng quản lý
các BindingManagerBase. Các đối tượng kế thừa từ lớp Control đều có thể có BindingContext. Tuy
nhiên, chỉ có Form và các điều khiển chứa các điều khiển khác như Groupbox, TabControl, Panel mới có
thể tạo một BindingContext để quản lý các BindingManagerBase hiển thị dữ liệu của các điều khiển
chứa trong nó.
Tuy cùng liên kết với một nguồn dữ liệu (cách tham chiếu hoàn toàn giống nhau), nhưng hai
BindingContext sẽ phát sinh hai BindingManagerBase khác nhau và không đồng bộ dữ liệu với nhau.

I.7.4. Các thủ tục nhập xuất dữ liệu trên màn hình
Để hiển thị dữ liệu trên màn hình, chúng ta sử dụng các điều khiển đã đề cập ở trên thông qua thuộc
tính liên kết dữ liệu và thường có các thủ tục nhập xuất sau:
ƒ Thủ tục Xuat_ho_so_<ten_bang>: xuất các trị của dòng đang làm việc ra các điều khiển trên
màn hình
ƒ Thủ tục Xuat_ho_so_<ten_bang>_moi: xuất các trị mặc định ra các điều khiển trên màn hình
để chuẩn bị tiếp nhận thông tin của dòng mới
ƒ Thủ tục Nhap_ho_so_<ten_bang>: nhập trị của các điều khiển trên màn hình vào các cột tương
ứng trên dòng đang làm việc.
ƒ Thủ tục Xuat_danh_sach_chon_<ten_bang>: sử dụng khi cấp nguồn liệt kê cho các điều khiển
ComboBox, ListBox, ListCheckBox

Học phần 3 – VB.NET Trang 151/187


Tài liệu hướng dẫn giảng dạy

ƒ Thủ tục Xuat_luoi_<ten_bang>: sử dụng khi xuất dữ liệu của bảng ra lưới (DataGrid)

II. Màn hình đơn


II.1. Các khai báo
Nguồn dữ liệu cho màn đơn chỉ là một bảng, phần khai báo cho màn hình này thường như sau:
Ví dụ:

Private <bang_du_lieu> As <XL_TEN_BANG>


Private Them_moi As Boolean = False
Private WithEvents Danh_sach As BindingManagerBase

ƒ <bang_du_lieu> là biến tham chiếu đến đối tượng của lớp xử lý nghiệp vụ trên màn hình.
ƒ Them_moi là biến theo dõi trạng thái thêm mới của dòng đang làm việc trên màn hình.
ƒ Danh_sach là biến tham chiếu đến BindingManagerBase của <bang_du_lieu> đang hiển thị trên
màn hình

II.2. Các thủ tục nhập xuất


Thực hiện nhập xuất trên màn hình đơn, chúng ta có ba thủ tục sau:
ƒ Xuat_ho_so_<ten_bang>:
Private Sub Xuat_ho_so_<ten_bang> ()
If Danh_sach.Position >= 0 Then
Them_moi = False
<Điều khiển 1>.<Thuộc tính liên kết dữ liệu> = _
Danh_sach.Current(<Cột 1>)
<Điều khiển 2>.<Thuộc tính liên kết dữ liệu> = _
Danh_sach.Current(<Cột 2>)
. . .
Else
Xuat_ho_so_<ten_bang>_moi
End If
End Sub

ƒ Xuat_ho_so_<ten_bang>_moi:
Private Sub Xuat_ho_so_<ten_bang>_moi()
Them_moi = True
<Điều khiển 1>.<Thuộc tính liên kết dữ liệu> = _
<Giá trị mặc định của cột hoặc của kiểu>
<Điều khiển 2>.<Thuộc tính liên kết dữ liệu> = _
<Giá trị mặc định của cột hoặc của kiểu>
. . .
End Sub

Học phần 3 – VB.NET Trang 152/187


Tài liệu hướng dẫn giảng dạy

ƒ Nhap_ho_so_<ten_bang>:
Private Sub Nhap_ho_so_<ten_bang>()
Danh_sach.Current(<Cột 1>) = <Điều khiển 1>.<Thuộc tính liên kết dữ
liệu>
Danh_sach.Current(<Cột 2>) = <Điều khiển 2>.<Thuộc tính liên kết dữ
liệu>
. . .
End Sub

Nếu trên màn hình có sử dụng các điều khiển liệt kê (ListControl) như ComboBox, ListBox,
CheckListBox, lúc này cần phải có thêm nguồn dữ liệu liệt kê cho điều khiển (<bang_liet_ke>) và có
thêm thủ tục:
ƒ Xuat_danh_sach_chon_<ten_bang>:
‘ <bang_liet_ke> là đối tượng cung cấp danh sách liệt kê cho điều khiển
Private Sub Xuat_danh_sach_chon_<ten_bang>()
<Điều khiển liệt kê>.DisplayMember = _
<Tên cột muốn hiển thị trên bảng liệt kê>
<Điều khiển liệt kê>.ValueMember = _
<Tên cột muốn liên kết trên bảng dữ liệu>
<Điều khiển liệt kê>.DataSource = <bang_liet_ke>
End Sub

Nếu màn hình hiển thị dữ liệu dưới dạng dòng cột sử dụng DataGrid, thủ tục xuất lưới sẽ là:
ƒ Xuat_luoi_<ten_bang>:
Private Sub Xuat_luoi_<ten_bang>()
<Điều khiển lưới>.DataSource = <bang_du_lieu>
End Sub

II.3. Các hàm kiểm tra


Trước khi thực hiện nhập dữ liệu vào DataTable, cần kiểm tra dữ liệu nhập của mỗi điều khiển có hợp
lệ (không vi phạm các ràng buộc toàn vẹn dữ liệu, miền giá trị, v.v...)
Các hàm hiểm tra trả về trị Boolean: True là hợp lệ, False là không hợp lệ
Nội dung các hàm kiểm tra như sau:
ƒ Kiem_tra_<ten cot > As Boolean: (số lượng tùy theo số điều khiển cần kiểm tra)
Private Function Kiem_tra_<ten_cot> As Boolean
Dim Ketqua As Boolean = <điều kiện giá trị trên điều khiển muốn kiểm tra
hợp lệ>
If Not Ketqua Then
' Thông báo lỗi
<Điều khiển>.Focus
' Phần này thay đổi tùy mỗi trường hợp
[Else

Học phần 3 – VB.NET Trang 153/187


Tài liệu hướng dẫn giảng dạy

Ketqua = <điều kiện kiểm tra khác trên cùng điều khiển nếu có>
If Not Ketqua Then
' Thông báo lỗi
<Điều khiển>.Focus
End If]
End If
Return Ketqua
End Function

ƒ Kiem_tra_ghi_<ten_bang > As Boolean: phối hợp các hàm kiểm tra trên để lấy kết quả tổng
hợp
Private Function Kiem_tra_ghi_<ten_bang> As Boolean
Dim Ketqua As Boolean = Kiem_tra_<ten_cot_1> AndAlso _
Kiem_tra_<ten_cot_2> ...
Return Ketqua
End Function

ƒ Kiem_tra_huy_<ten_bang > As Boolean: kiểm tra hủy dữ liệu có vi phạm ràng buộc toàn vẹn
không (kiểm tra trên các bảng nhiều)
Private Function Kiem_tra_huy_<ten_bang> As Boolean
Dim Ketqua As Boolean
Dim bang As _
New XL_<TEN_BANG_CON>(<điều kiện lọc theo khóa bảng kiểm tra>)
Ketqua = (bang.So_dong = 0)
' kiểm tra trên các bảng con khác nếu cần
Return Ketqua
End Function

II.4. Các xử lý sự kiện


Trên màn hình đơn, chúng ta thường có các xử lý sự kiện sau:
ƒ Form_Load: Khởi tạo bảng dữ liệu và thực hiện xuất danh sách chọn (nếu có), xuất lưới, xuất
hồ sơ
Private Sub MH_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
<bang_du_lieu> = New <XL_TEN_BANG>
Danh_sach = Me.BindingContext(<bang_du_lieu>)
Xuat_luoi_<ten_bang>()
Xuat_ho_so_<ten_bang>()
End Sub

Học phần 3 – VB.NET Trang 154/187


Tài liệu hướng dẫn giảng dạy

ƒ Sự kiện nhấn của các nút lệnh di chuyển: thay đổi dòng hiện hành nếu hợp lệ
Private Sub Dau_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles Dau.Click
If Danh_sach.Position > 0 Then
Danh_sach.Position = 0
End If
End Sub

Private Sub Truoc_Click(ByVal sender As Object, ByVal e As _


System.EventArgs) Handles Truoc.Click
If Danh_sach.Position > 0 Then
Danh_sach.Position -= 1
End If
End Sub

Private Sub Sau_Click(ByVal sender As Object, ByVal e As _


System.EventArgs) Handles Sau.Click
If Danh_sach.Position < Danh_sach.Count - 1 Then
Danh_sach.Position += 1
End If
End Sub

Private Sub Cuoi_Click(ByVal sender As Object, ByVal e As _


System.EventArgs) Handles Cuoi.Click
If Danh_sach.Position < Danh_sach.Count - 1 Then
Danh_sach.Position = Danh_sach.Count - 1
End If
End Sub

ƒ Sự kiện nhấn của nút thêm: Thực hiện xuất hồ sơ mới và đưa con trỏ nhập liệu về điều khiển
bắt đầu
Private Sub Them_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles Them.Click
Xuat_ho_so_<ten bang>_moi()
<Điều khiển bắt đầu>.Focus
End Sub

Sự kiện nhấn của nút ghi: Thực hiện kiểm tra ghi. Nếu hợp lệ, thực hiện các bước:
+ Nếu Them_moi là True (đang thêm), thêm dòng mới trên Danh_sach
+ Nhập hồ sơ
+ Thực hiện ghi dữ liệu của lớp xử lý

Học phần 3 – VB.NET Trang 155/187


Tài liệu hướng dẫn giảng dạy

+ Xuất hồ sơ
Private Sub Ghi_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles Ghi.Click
If Kiem_tra_ghi_<ten bang>() Then
If Them_moi Then Danh_sach.AddNew()
Nhap_ho_so_<ten bang>()
Danh_sach.EndCurrentEdit()
<bang_du_lieu>.Ghi()
Xuat_ho_so_<ten bang>()
End If
End Sub

ƒ Sự kiện nhấn của nút không: Thực hiện xuất lại thông tin trước đó.
Private Sub Khong_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles Khong.Click
Xuat_ho_so_<ten bang>()
End Sub

ƒ Sự kiện nhấn của nút hủy: Nếu Them_moi là True, thực hiện xuất hồ sơ; ngược lại nếu kiểm tra
hủy hợp lệ và đồng ý xóa thực hiện:
+ Đánh dấu hủy dòng hiện hành trên Danh_sach
+ Thực hiện ghi dữ liệu của lớp xử lý
+ Xuất hồ sơ
Private Sub Huy_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles Huy.Click
If Them_moi Then
Xuat_ho_so_<ten bang>()
Exit Sub
Else If Kiem_tra_huy_<ten bang>() Then
If MsgBox("Đồng ý hủy ?", MsgBoxStyle.Question + _
MsgBoxStyle.YesNo,"Xin cho biết") = MsgBoxResult.Yes Then
Danh_sach.Current.Delete()
<bang_du_lieu>.Ghi()
End If
Else
' Thông báo lỗi
End If
End Sub

ƒ Sự kiện CurrentChanged của Danh_sach: Thực hiện xuất hồ sơ, nếu không phải đang thêm mới
Private Sub Danh_sach_CurrentChanged(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles Danh_sach.CurrentChanged

Học phần 3 – VB.NET Trang 156/187


Tài liệu hướng dẫn giảng dạy

If Not Them_moi Then


Xuat_ho_so_<ten_bang>()
End If
End Sub

III. Màn hình một nhiều


Màn hình này hiển thị dữ liệu của bảng một và dữ liệu của bảng nhiều ứng với dòng hiện hành trên
bảng một. Dữ liệu cho màn hình gồm bảng một và bảng nhiều.
Có thể có các dạng :

III.1. Màn hình một-nhiều hai trang


Màn hình gồm các điều khiển cho bảng một, lưới cho bảng một và lưới cho bảng nhiều. Các điều khiển
bảng một trên một tab của TabControl và tab còn lại chứa lưới bảng một. Lưới bảng nhiều được đặt
trên Form.
Bảng dữ liệu phía nhiều phải được khai báo và có thể:

ƒ Được đọc theo trị cột khóa bảng phía một khi bảng phía một thay đổi dòng làm việc và xuất ra
lưới
ƒ Hoặc được lọc theo trị cột khóa bảng phía một khi bảng phía một thay đổi dòng làm việc và
xuất ra lưới (nếu đã được đọc toàn bộ từ đầu)

Ví dụ: Xử lý bảng nhiều được đọc theo khóa bảng một (khi số liệu bảng nhiều quá lớn)

Private <bang_du_lieu> As <XL_TEN_BANG>


Private <bang_du_lieu_phia_nhieu> As <XL_TEN_BANG_NHIEU>
Private Danh_sach As BindingManagerBase
Private Danh_sach_nhieu As BindingManagerBase

Học phần 3 – VB.NET Trang 157/187


Tài liệu hướng dẫn giảng dạy

Private Sub MH_Load(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load
....
Call Danh_sach_CurrentChanged(sender, e)
End Sub

Private Sub Xuat_luoi_<ten_bang_nhieu>()


LUOI_<TEN_BANG_NHIEU>.DataSource = <bang_du_lieu_phia_nhieu>
End Sub

Private Sub danh_sach_CurrentChanged(ByVal sender As Object, ByVal e As _


System.EventArgs) Handles danh_sach.CurrentChanged ...
Dim khoa As Integer = 0
If Not Them_moi AndAlso Danh_sach.Position >= 0 Then
...
khoa = Danh_sach.Current(<Khóa>)
End If
<bang_du_lieu_phia_nhieu> As New <XL_TEN_BANG_NHIEU> _
("điều kiện lọc theo khóa bảng một")
Xuat_luoi_<ten_bang_nhieu>()
End Sub

Ví dụ: Xử lý bảng nhiều được đọc hết và được lọc theo khóa bảng một khi dòng hiện hành bảng một
thay đổi (khi số liệu bảng nhiều không lớn)

Private <bang_du_lieu_phia_nhieu> As <XL_TEN_BANG_NHIEU>

Private Sub MH_Load(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load
....
<bang_du_lieu_phia_nhieu> As New <XL_TEN_BANG_NHIEU>()
Xuat_luoi_<ten_bang_nhieu>()
Call Danh_sach_CurrentChanged(sender, e)
End Sub

Private Sub Xuat_luoi_<ten_bang_nhieu>()


LUOI_<TEN_BANG_NHIEU>.DataSource = <bang_du_lieu_phia_nhieu>
End Sub

Private Sub danh_sach_CurrentChanged(ByVal sender As Object, ByVal e As _

Học phần 3 – VB.NET Trang 158/187


Tài liệu hướng dẫn giảng dạy

System.EventArgs) Handles danh_sach.CurrentChanged ...


Dim khoa As Integer = 0
If Not Them_moi AndAlso Danh_sach.Position >=0 Then
...
khoa As Integer = Danh_sach.Current(<Khóa>)
End If
<bang_du_lieu_phia_nhieu>.Loc_du_lieu("điều kiện lọc theo khóa bảng một")
End Sub

III.2. Màn hình một-nhiều ba trang


Màn hình có TabControl ba tab : một tab chứa các điều khiển bảng một, một tab chứa lưới bảng một
và một tab chứa lưới bảng nhiều. Cách thức xử lý cũng như trên.

Học phần 3 – VB.NET Trang 159/187


Tài liệu hướng dẫn giảng dạy

IV. Màn hình lọc dữ liệu


IV.1. Màn hình lọc một điều kiện
Màn hình gồm các điều khiển cho bảng một và lưới (hoặc ListBox) cho bảng nhiều. Điều khiển của
bảng một thường có một Combobox, ListBox liệt kê các giá trị giúp người dùng lựa chọn. Chúng ta
dùng sự kiện SelectedIndexChanged để lọc dữ liệu

Trên đây là một dạng khác của màn hình lọc theo một điều kiện: (các bảng vở kịch, diễn viên, tham gia
được đọc khi mở màn hình)
ƒ Diễn viên được phân vai hiển thị dữ liệu THAM_GIA lọc theo vở kịch được chọn
ƒ Danh sách diễn viên hiển thị dữ liệu DIEN_VIEN đã loại trừ các diễn viên được phân vai
Ví dụ: bang_tham_gia và bang_dien_vien được khởi tạo khi mở màn hình

Private Sub MVK_SelectedIndexChanged(ByVal sender As Object, ByVal e As _


System.EventArgs) Handles Danh_sach_chon_vo_kich.SelectedIndexChanged
bang_tham_gia.Loc_du_lieu("MVK=" & MVK.SelectedValue)
Dim chuoi As String = Lap_danh_sach_MDV(bang_tham_gia)
If chuoi <>"" Then chuoi = "MDV Not In(" & chuoi & ")"
bang_dien_vien.Loc_du_lieu(chuoi)
End Sub

Private Function Lap_danh_sach_MDV(bang As XL_BANG) As String


Dim ketqua As String = ""
For i As Integer = 0 To bang.So_dong - 1
ketqua &= bang.DefaultView(i)("MDV") & ","
Next
If ketqua.Length > 0 Then ketqua = _
ketqua.SubString(0, ketqua.Length - 1)
Return ketqua
Học phần 3 – VB.NET Trang 160/187
Tài liệu hướng dẫn giảng dạy

End Function

ƒ Các nút >, >> thực hiện thêm các dòng chọn trên Danh sách diễn viên vào bang_tham_gia và
lọc lại dữ liệu trên bang_dien_vien
ƒ Các nút <, << thực hiện hủy các dòng chọn trên Diễn viên được phân vai khỏi bang_tham_gia
và lọc lại dữ liệu trên bang_dien_vien

IV.2. Màn hình lọc hai điều kiện


Màn hình gồm hai điều khiển (ComboBox, ListBox hoặc Option Group) và lưới để hiển thị dữ liệu lọc.
Chúng ta dùng sự kiện SelectedIndexChanged của Combobox hoặc ListBox, CheckedChanged của
Option để lọc dữ liệu.

V. Màn hình một-nhiều-nhiều


Màn hình này hiển thị dữ liệu của bảng một, dữ liệu của bảng nhiều thứ nhất ứng với dòng hiện hành
trên bảng một và dữ liệu của bảng nhiều thứ hai ứng với dòng hiện hành trên bảng nhiều thứ nhất.
Màn hình gồm các điều khiển cho bảng một, lưới cho bảng nhiều thứ nhất và lưới cho bảng nhiều thứ
hai. Các điều khiển cho bảng một thường có một ComboBox để lọc dữ liệu cho bảng nhiều thứ nhất.
Khi chọn dòng trên lưới của bảng nhiều thứ nhất, lọc (hoặc đọc) dữ liệu của bảng nhiều thứ hai

VI. Một số kỹ thuật trong hiển thị dữ liệu


VI.1. Tạo lớp DataGridColumnStyle chuyển đổi dữ liệu hiển thị
Trên lưới, có những trường hợp cần cột hiển thị dữ liệu khác với dữ liệu lưu trữ như cột MÃ hiển thị
TÊN. Chúng ta có thể thực hiện thông qua việc tạo một kiểu DataGridColumnStyle mới đáp ứng nhu
cầu này kế thừa từ DataGridTextBoxColumn.
DataGridTextBoxColumn kế thừa từ DataGridColumnStyle và có một DataGridTextBox (phát sinh từ lớp
TextBox). Điều khiển TextBox được đưa vào tập hợp Controls của DataGrid. Mỗi lần người dùng bắt
đầu soạn thảo trên ô của cột có kiểu DataGridTextBoxColumn, DataGridTextBox được di chuyển đến vị
trí soạn thảo và người dùng chỉnh sửa trên chính DataGridTextBox. Giá trị hiển thị trên lưới và cập nhật
vào bảng thông qua hai phương thức GetColumnValueAtRow, SetColumnValueAtRow.
Cách giải quyết :
ƒ Để có giá trị hiển thị cho cột, chúng ta sử dụng một tập hợp (Collection) chứa tất cả những giá
trị cần hiển thị tương ứng.
ƒ Giá trị đưa vào tập hợp thuộc một Class với hai thuộc tính đọc ghi chứa giá trị hiển thị và giá trị
lưu trữ do chúng ta xây dựng.
ƒ Lớp DataGridColumnStyle được tạo sẽ có tập hợp (collection) các đối tượng của lớp vừa tạo ở
trên lấy giá trị do người dùng cung cấp thông qua các phương thức thêm xóa của collection.
ƒ Trong hàm GetColumnValueAtRow, chúng ta tìm và trả về giá trị hiển thị tương ứng trong tập
hợp. Loại cột này dùng để hiển thị thông tin, không cho cập nhật nên chúng ta sẽ không sử
dụng thủ tục SetColumnValueAtRow.
Xin tham khảo giáo trình phần gợi ý tạo Class mới của DataGridColumnStyle.

Học phần 3 – VB.NET Trang 161/187


Tài liệu hướng dẫn giảng dạy

VI.2. Tạo lớp DataGridColumnStyle có ComboBox


Loại này có một ComboBox chứa danh sách liệt kê để người dùng chọn lựa. Ngoài ra đây cũng là cột có
thể có nhu cầu hiển thị khác nội dung lưu trữ nên chúng ta kế thừa từ lớp TranslateColumn ở trên.

Các yêu cầu cho loại cột này là:


ƒ Đưa vào một ComboBox
ƒ Xử lý cập nhật khi giá trị trên cột thay đổi qua ComboBox
Cách thực hiện:

ƒ Khai báo một ComboBox mới và đưa vào tập hợp Controls của lớp và diều khiển này sẽ ẩn hiện
theo TextBox của cột và sẽ di chuyển đến vùng hiện hành của lưới.
ƒ DisplayMember, ValueMember và DataSource của ComboBox sẽ được gán thông qua một
phương thức.
ƒ Để cập nhật dữ liệu cho lưới, chúng ta gán SelectedValue của ComboBox sau khi chọn thông
qua phương thức SetColumnAtRowValue
Xin xem thêm giáo trình.

VI.3. Tạo lớp DataGridColumnStyle cho phép định dạng chi tiết
Với lớp DataGridTextBoxColumn, chúng ta không thể định dạng riêng cho một ô. Vì vậy, cần xây dựng
một lớp có thể cho phép định dạng riêng biệt qua việc tạo một kiểu DataGridColumnStyle mới kế thừa
từ DataGridTextBoxColumn (xem thêm trong giáo trình)

VI.4. Minh họa sử dụng


VI.4.1. Lớp TranslateColumn
Chúng ta thiết kế lưới hiển thị các diễn viên sử dụng lớp TranslateColumn hiển thị dữ liệu cột Phai trên
bảng

– Khai báo cột TranslateColumn khi thiết kế:


ƒ Định cột Phai kiểu DataGridTextBoxColumn (giả sử được đặt tên là cotPhai) với MappingName là
"Phai"
ƒ Sau đó chuyển sang cửa sổ Code, vùng Windows Form Designer generated code, tìm và sửa
kiểu của cột này từ DataGridTextBoxColumn -> TranslateColumn
ƒ Viết thủ tục cấp nguồn hiển thị cho cotPhai và gọi trong sự kiện Form_Load
Ví dụ:

Private Sub Nguon_hien_thi()


' Tri là lớp đã xây dựng (xem giáo trình)
cotPhai.Tap_hop.Add(New Tri(False, "Nữ"))

Học phần 3 – VB.NET Trang 162/187


Tài liệu hướng dẫn giảng dạy

cotPhai.Tap_hop.Add(New Tri(True, "Nam"))


End Sub

– Thiết kế lưới bằng lệnh:


Ví dụ: Lưới có tên LUOI_DIEN_VIEN

Private Sub Thiet_ke_luoi_dien_vien()


Dim kieu_the_hien As New DataGridTableStyle
kieu_the_hien.MappingName = "DIEN_VIEN"
Dim cotHo_ten_DV As New DataGridTextBoxColumn
' các lệnh thiết kế cột ...
Dim cotPhai As New TranslateColumn
cotPhai.HeaderText = "Phái"
cotPhai.MappingName = "Phai"
cotPhai.NullText = ""
cotPhai.Width = 60
cotPhai.Tap_hop.Add(New Tri(False, "Nữ"))
cotPhai.Tap_hop.Add(New Tri(True, "Nam"))
Dim cotNgay_sinh As New DataGridTextBoxColumn
' các lệnh thiết kế cột ...
Dim cotDia_chi As New DataGridTextBoxColumn
' các lệnh thiết kế cột ...
kieu_the_hien.GridColumnStyles.AddRange(New DataGridColumnStyle() _
{cotHo_ten_DV, cotPhai, cotNgay_sinh, cotDia_chi})
LUOI_DIEN_VIEN.TableStyles.Add(kieu_the_hien)
End Sub

Sau đó, gọi thực hiện Thiet_ke_luoi_dien_vien trong sự kiện Form_Load

VI.4.2. Lớp ComboBoxColumn


Với yêu cầu thiết kế màn hình như hình bên
– Khai báo cột ComboBoxColumn khi thiết kế
ƒ Định cột Diễn viên kiểu DataGridTextBoxColumn (giả
sử được đặt tên là cotMDV) với MappingName là
"MDV"
ƒ Sau đó chuyển sang cửa sổ Code, vùng Windows
Form Designer generated code, tìm và sửa kiểu của
cột này từ DataGridTextBoxColumn ->
ComboBoxColumn
ƒ Trong sự kiện Form_Load, sau khi có dữ liệu của
DIEN_VIEN (qua biến bang_dien_vien của lớp
XL_DIEN_VIEN), gọi phương thức
Cap_nguon_hien_thi_liet_ke

Học phần 3 – VB.NET Trang 163/187


Tài liệu hướng dẫn giảng dạy

Ví dụ:

bang_dien_vien =New XL_DIEN_VIEN


cotMDV.Cap_nguon_hien_thi_liet_ke(bang_dien_vien, "MDV", "Ho_ten_DV")

– Thiết kế lưới bằng lệnh


Ví dụ: Lưới có tên LUOI_THAM_GIA

Private Sub Thiet_ke_luoi_tham_gia()


Dim kieu_the_hien As New DataGridTableStyle
kieu_the_hien.MappingName = "THAM_GIA"
Dim cotMDV As New ComboBoxColumn
cotMDV.HeaderText = "Diễn viên"
cotMDV.MappingName = "MDV"
cotMDV.NullText = ""
cotMDV.Width = 190
cotMDV.Cap_nguon_hien_thi_liet_ke (bang_dien_vien, "MDV", "Ho_ten_DV")
kieu_the_hien.GridColumnStyles.Add(cotMDV)
LUOI_THAM_GIA.TableStyles.Add(kieu_the_hien)
End Sub

Sau đó, gọi thực hiện Thiet_ke_luoi_tham_gia trong sự kiện Form_Load

VI.4.3. Lớp ColoredColumn


Với yêu cầu thiết kế lưới hiển thị vở kịch như sau:
ƒ Tạo thêm cột số diễn viên tham gia vở kịch
ƒ Nếu số diễn viên tham gia vượt quá trị nào đó, sẽ đổi màu chữ, màu nền, hiệu ứng của font
chữ, canh lề nội dung: canh phải, tiêu đề: canh trái

– Khai báo cột ColoredColumn khi thiết kế:


ƒ Định cột Số diễn viên tham gia kiểu DataGridTextBoxColumn (giả sử được đặt tên là cotSo_dv)
với MappingName là "So_dv"
ƒ Chuyển sang cửa sổ Code, vùng Windows Form Designer generated code, tìm và sửa kiểu của
cột này từ DataGridTextBoxColumn -> ColoredColumn. Sau đó định lại thuộc tính
Canh_le_noi_dung trên cửa sổ Properties là Far
ƒ Xử lý sự kiện Phat_sinh_bien_co_ve_o như sau:
Ví dụ:

Private Sub cotSo_dv_Phat_sinh_bien_co_ve_o (ByRef e As _


Tham_so_ve_o) Handles cotSo_dv.Phat_sinh_bien_co_ve_o

Học phần 3 – VB.NET Trang 164/187


Tài liệu hướng dẫn giảng dạy

If CInt(e.Gia_tri) > 3 Then


e.Font_Chu = New Font(LUOI_VO_KICH.Font, FontStyle.Italic)
e.Mau_nen = Brushes.Cyan
e.Mau_chu = Brushes.Blue
End If
End Sub

Học phần 3 – VB.NET Trang 165/187


Tài liệu hướng dẫn giảng dạy

Bài 9
BÁO BIỂU CRYSTAL REPORT
Tóm tắt
Lý thuyết 6 tiết - Thực hành 10 tiết

Mục tiêu Các mục chính Bài tập

Bài học này giúp cho học viên cách 1. Giới thiệu CrysTal Reportl 5.15, 5.16, 5.18,
thiết kế báo biểu theo mô hình Pul, 2. Tạo báo biểu mô hình Pull, Push 5.19
Push trong VB.Net.
Bài làm thêm: 5.17

Học phần 3 – VB.NET Trang 166/187


Tài liệu hướng dẫn giảng dạy

I. Giới thiệu Crystal Report


Crystal Report là phần mềm thiết kế báo biểu chuyên nghiệp được tích hợp trong các phiên bản của
Visual Studio. Phiên bản Studio .NET của Microsoft được tích hợp Crystal Report 8.5.
Bản thân Crystal Report là một phần mềm tạo báo biểu độc lập với rất nhiều chức năng thiết kế báo
biểu và dịch vụ. Người dùng có thể kết nối với nhiều nguồn dữ liệu khác nhau bằng các ODBC Driver.
Báo biểu khi tạo ra cũng có thể được lưu trữ thành những file .rpt độc lập, ở dạng có dữ liệu hay không
có dữ liệu. Sau đó, file .rpt có thể được chuyển tới người dùng khác và mở bằng Crystal Report hay có
thể kết hợp với các ứng dụng viết bằng Visual Basic, Visual C++.

Xét về mặt thiết kế báo biểu, Crystal Report cung cấp đầy đủ các chức năng đinh dạng dữ liệu và các
chức năng phân nhóm, tính toán, sub – report và kể cả khả năng lập trình bằng formula dựa trên các
fomula field. Người dùng ngoài việc sử dụng formula field còn có thể tự xây dựng bộ thư viện hàm của
riêng mình và đưa vào Crystal Report thông qua các DLL. Bên cạnh khả năng thiết kế báo biểu thông
thường, Crystal Report còn cung cấp chức năng thiết kế biểu đồ dựa trên nguồn dữ liệu lấy từ CSDL.
Xét về mặt sử dụng báo biểu, công cụ hiển thị của Crystal Report cho phép người dùng tương tác rất
linh hoạt. Báo biểu hiển thị có thể được lọc lại các dữ liệu cần thiết hay xem một phần báo biểu bằng
cách sử dụng cấu trúc hiển thị dữ liệu dạng cây. Các Section trong báo biểu cũng có thể mở rộng hay
thu hẹp để hiển thị hay che bớt những dữ liệu không cần thiết. Một khi báo biểu đã được xây dựng,
người dùng còn có thể Export sang các dạng file khác như Word, Excel, HTML,…
Bằng cách tích hợp Crystal Report 8.5, Visual Studio .NET đem lại cho người dùng một công cụ xây
dựng báo biểu hiệu quả, tiết kiệm nhiều thời gian so với việc phải sử dụng các đối tượng in ấn để tự
phát sinh báo biểu. Chúng ta có thể sử dụng Report Expert để tạo ra báo biểu dựa vào wizard và
template định sẵn hay thiết kế chi tiết báo biểu bằng tay. Nội dung phần này không đề cập đến các chi
tiết thiết kế cụ thể (có thể tham khảo cách tạo báo biểu trên Crystal Report trong giáo trình Visual
Basic tập hai) nhưng tập trung vào việc tạo mới báo biểu trong Visual Studio .Net, hiển thị báo biểu
trong ứng dụng và sử dụng DataSet làm nguồn dữ liệu cho báo biểu.

II. Tạo báo biểu

Học phần 3 – VB.NET Trang 167/187


Tài liệu hướng dẫn giảng dạy

Báo biểu là một phần của project do đó, để tạo mới một báo biểu chúng ta thực hiện thông qua menu
Project | Add new item… và lần lượt thực hiện

– Trong phần Templates, chọn mục Crystal Report để tạo mới một báo biểu.
– Trong phần Name của hộp thoại Add New Item nhập vào tên file báo biểu cần tạo.
– Khi nhấn nút Open, Visual Studio .Net tự động chuyển đổi sang giao diện của Crystal Report để
chúng ta thực hiện việc tạo mới báo biểu. Có thể chọn tạo mới báo biểu ở một trong hai hình thức:
Wizard (Using Report Expert) hay tự thiết kế từ đầu (Blank Report). Chúng ta cũng có thể mở một
báo biểu đã tạo sẵn để đưa vào project.

– Khi chọn Blank Report, khác với sử dụng phần mềm Crystal Report độc lập, Visual Studio .NET sẽ
chuyển ngay sang màn hình thiết kế mà không chọn CSDL cho báo biểu (xem hình trên)
– Để chọn CSDL cho báo biểu, nhắp chuột phải trên mục Database Fields và chọn mục Add/Remove
Database
– Một điểm cần chú ý khác trong quá trình thiết kế báo biểu đó là một số thay đổi trong giao diện so
với phần mềm Crystal Report chạy độc lập. Ví dụ, chúng ta sẽ tìm thấy TextObject trong phần
Toolbox hay thuộc tính của các đối tượng thiết kế có thể thay đổi trực tiếp từ cửa sổ Properties như
khi đang thiết kế form
– Cuối cùng, cũng giống như Crystal Report Designer trên Visual Basic 6.0, chúng ta không thể
chuyển sang chế độ Preview để xem kết quả thiết kế báo biểu, thay vào đó cần phải sử dụng đối
tượng Crystal Report Viewer của Visual Studio .NET.
Màn hình dưới là thiết kế của báo biểu hiển thị danh sách các mặt hàng theo từng loại, lấy nguồn dữ
liệu từ CSDL Northwind của SQL Server.

Học phần 3 – VB.NET Trang 168/187


Tài liệu hướng dẫn giảng dạy

II.1. Nguồn dữ liệu cho báo biểu


Crystal Report kết nối với nguồn dữ liệu thông qua các trình dữ liệu của nó. Mỗi trình được viết để xử lý
cho một loại dữ liệu hoặc cho một kỹ thuật truy xuất dữ liệu cụ thể.
Để tạo thuận lợi cho người lập trình, các trình dữ liệu của Crystal Report cung cấp hai mô hình truy
xuất: PULL và PUSH

II.1.1. Pull Model (mô hình kéo)

Mô hình Pull
Trong mô hình này, trình sẽ kết nối với nguồn dữ liệu và lấy về dữ liệu yêu cầu. Kết nối với nguồn và
lệnh SQL truy xuất dữ liệu đều do Crystal Reports xử lý; chúng ta không phải viết dòng lệnh nào. Nếu
không có dòng lệnh nào viết cho lúc thực hiện, báo biểu sử dụng mô hình Pull.

II.1.2. Push Model (mô hình đẩy)


Ngược lại, mô hình đẩy (Push) đòi hỏi chúng ta phải viết lệnh kết nối dữ liệu, thực hiện truy xuất dữ
liệu để tạo Recordset hoặc DataSet chứa các field cần thiết cho báo biểu. Mô hình này cho phép chia sẽ
kết nối trong ứng dụng và lọc dữ liệu trước khi đưa vào báo biểu.

Học phần 3 – VB.NET Trang 169/187


Tài liệu hướng dẫn giảng dạy

Mô hình Push

II.2. Sử dụng Crystal Report Viewer để hiển thị báo biểu


Để hiển thị báo biểu, chúng ta cần có điều khiển CrystalReportViewer. Có thể thiết kế riêng một form
chứa điều khiển này để hiển thị báo biểu và cung cấp thêm các chức năng đặc biệt nào đó trong
chương trình. Trong trường hợp đơn giản, bản thân CrystalReportViewer cũng đã cung cấp khá đầy đủ
các chức năng hiển thị báo biểu và tương tác với người dùng. Do đó, chúng ta có thể sẽ tạo ra form và
đối tượng CrystalReportViewer ngay trong đoạn lệnh của chương trình.

CrystalReportViewer trên ToolBoox


Ví dụ: Sau đây khai báo một form và đối tượng CrystalReportViewer để hiển thị báo biểu
CrystalReport1.rpt vừa được tạo ở trên

' Tạo form mới


Dim f As New Form
' Tạo đối tượng CrystalReportViewer
Dim cv As New CrystalDecisions.Windows.Forms.CrystalReportViewer
' Đưa cv vào trong form, đặt cv.Dock = Fill để chiếm đầy màn hình
f.Controls.Add(cv)
cv.Dock = DockStyle.Fill

' Gán report sẽ hiển thị trên cv là một thể hiện của CrystalRport1
cv.ReportSource = New CrystalReport1
f.ShowDialog()

Khi thực hiện chương trình với đoạn lệnh trên, chúng ta sẽ có một màn hình hiển thị report tương tự
như hình dưới.

CrystalReportViewer có khá đầy đủ các chức năng, từ lật trang, in ấn, gửi mail, phóng lớn/thu nhỏ cho
tới tìm kiếm, định vị các group,…

Học phần 3 – VB.NET Trang 170/187


Tài liệu hướng dẫn giảng dạy

II.3. Nguồn dữ liệu cho báo biểu từ DataSet


Một điểm đặc biệt trong Visual Studio .NET là có thể tạo nguồn dữ liệu cho báo biểu từ một DataSet
(mô hình Push). Sử dụng DataSet làm nguồn dữ liệu của báo biểu cho phép tạo ra những báo biểu
không cần kết nối với CSDL hay thậm chí tạo ra những báo biểu trong các ứng dụng hoạt động không
cần có CSDL đi cùng. Chẳng hạn, có thể lấy cấu trúc DataSet từ một file XML làm nguồn dữ liệu cho
báo biểu.
Để gán nguồn dữ liệu cho báo biểu, chúng ta cần một biến đối tượng là một thể hiện của báo biểu đã
thiết kế. Khi đã có một DataSet, chúng ta sử dụng phương thức SetDataSource của đối tượng báo biểu
để gán DataSet đó làm nguồn dữ liệu:

Ví dụ:

Dim Rpt As New CrystalReport1


Rpt.SetDataSource(ds)

Sau đây minh họa cách thiết kế báo biểu sử dụng DataSet làm nguồn dữ liệu.
ƒ Trong Project, tạo một DataSet mới
+ Menu Project | Add new item, chọn mục DataSet, trong phần Name, gõ vào tên của DataSet
là: Products_Schema.xsd
+ Thiết kế DataSet như sau:

Học phần 3 – VB.NET Trang 171/187


Tài liệu hướng dẫn giảng dạy

+ Lưu DataSet lại sau khi tạo xong cấu trúc bảng
ƒ Tạo mới một báo biểu, khi chọn nguồn dữ liệu cho báo biểu chúng ta chọn mục ADO.NET
DataSet
+ Chọn DataSet vừa tạo
+ Chọn 2 bảng Categories và Products làm nguồn dữ liệu
+ Chọn OK để lưu lại nguồn dữ liệu của báo biểu

ƒ Thiết kế báo biểu tương tự như của ví dụ trước


ƒ Trong đoạn lệnh hiển thị dữ liệu, sửa lại nội dung như sau:
Ví dụ:

Dim bo_doc_ghi As New Data.OleDb.OleDbDataAdapter _


("Select CategoryID, CategoryName From Categories;Select ProductID,
ProductName, " _
& "UnitPrice, UnitsInStock, CategoryID From Products" & _
"Provider=SQLOLEDB;Server=NTH;Initial Catalog=Northwind; User ID=sa")

bo_doc_ghi.TableMappings.Add ("Table", "Categories")


bo_doc_ghi.TableMappings.Add ("Table1", "Products")
Dim DS As New Products_Schema, rpt As New CrystalReport1

Dim f As New Form


Dim cv As New CrystalDecisions.Windows.Forms.CrystalReportViewer
f.Controls.Add(cv)
cv.Dock = DockStyle.Fill
rpt.SetDataSource(DS)

Học phần 3 – VB.NET Trang 172/187


Tài liệu hướng dẫn giảng dạy

rpt.RecordSelectionFormula = "{Categories.CategoryID} > 4"


cv.ReportSource = rpt
f.ShowDialog()

Khi chạy chương trình, báo cáo sẽ được hiển thị như sau:

Trên hình, dữ liệu đã được lọc lại so với báo cáo trước để chỉ hiển thị những Category có CategoryID
>4.

II.4. Định lại dữ liệu cho báo biểu từ nguồn CSDL


Trong mô hình Pull đã đề cập ở trên, khi khai báo nguồn dữ liệu trong thiết kế, chúng ta phải chỉ rõ
nguồn dữ liệu (đường dẫn của tập tin mdb hay thông tin đăng nhập trong SQL Server). Vì thế, lúc thực
thi, cần định lại thông tin nguồn CSDL.
Trước hết cần làm quen với một số đối tượng trong CrystalDecisions.CrystalReports.Engine:

Các đối tượng trong CrystalDecisions.CrystalReports.Engine


Tên Mô tả
Database Nguồn CSDL sử dụng cho báo biểu.
Table Thông qua chỉ số, tên trả về bảng tương ứng được sử dụng trong báo biểu.
Tables Tập hợp các bảng sử dụng trên báo biểu.

Báo biểu có thành phần Database cho biết nguồn dữ liệu hiển thị. Khi vị trí nguồn thay đổi, chúng ta
phải định lại vị trí nguồn mới cho báo biểu thông qua thông tin đăng nhập của Table, thuộc tập hợp
Tables của Database.
Thông tin đăng nhập thuộc lớp TableLogOnInfo trong không gian tên
CrystalDecisions.Shared.TableLogOnInfo với các thông tin:

Các thuộc tính của TableLogOnInfo

Học phần 3 – VB.NET Trang 173/187


Tài liệu hướng dẫn giảng dạy

Tên Mô tả
ConnectionInfo Đối tượng chứa thông tin kết nối của bảng.
DatabaseName Tên tập tin CSDL.
Password Mật khẩu truy cập nguồn CSDL
ServerName Tên server hoặc nguồn dữ liệu ODBC.
UserID Tên người dùng để truy cập CSDL.

Thông tin TableLogOnInfo của bảng có tính chỉ đọc và mặc định lưu giữ thông tin kết nối lúc chúng ta
khai báo nguồn để thiết kế báo biểu. Khi thay đổi và muốn cập nhật lại, chúng ta phải sử dụng phương
thức ApplyLogOnInfo của đối tượng Table với tham số là TableLogOnInfo chúng ta đã thay đổi.
Ví dụ: Minh họa khi nguồn dữ liệu là MS Access

Dim f As New Form()


' CReportVD là báo biểu đã tạo lúc thiết kế
Dim rpt As New CreportVD()
Dim cv As New CrystalDecisions.Windows.Forms.CrystalReportViewer()
f.Controls.Add(cv)
cv.Dock = DockStyle.Fill
Dim logOnInfo As CrystalDecisions.Shared.TableLogOnInfo
' Nếu các Table cùng từ một nguồn dữ liệu, chỉ cần định lại cho một bảng
là đủ
logOnInfo = rpt.Database.Tables(0).LogOnInfo
logOnInfo.ConnectionInfo.ServerName = <đường dẫn đến .mdb>
rpt.Database.Tables(0).ApplyLogOnInfo(logOnInfo)
cv.ReportSource = rpt
f.ShowDialog()

Ví dụ: Minh họa khi nguồn dữ liệu là SQL Server

Dim f As New Form()


' CReportVD là báo biểu đã tạo lúc thiết kế
Dim rpt As New CreportVD()
Dim cv As New CrystalDecisions.Windows.Forms.CrystalReportViewer()
f.Controls.Add(cv)
cv.Dock = DockStyle.Fill
Dim logOnInfo As CrystalDecisions.Shared.TableLogOnInfo
' Nếu các Table cùng từ một nguồn dữ liệu, chỉ cần định lại cho một bảng
là đủ
logOnInfo = rpt.Database.Tables(0).LogOnInfo
logOnInfo.ConnectionInfo.ServerName = <Tên server>
logOnInfo.ConnectionInfo.DatabaseName = <Tên CSDL>
logOnInfo.ConnectionInfo.UserID = <Người dùng>
logOnInfo.ConnectionInfo.Password = <Mật khẩu>

Học phần 3 – VB.NET Trang 174/187


Tài liệu hướng dẫn giảng dạy

rpt.Database.Tables(0).ApplyLogOnInfo(logOnInfo)
cv.ReportSource = rpt
f.ShowDialog()

II.5. Lọc dữ liệu báo biểu


Để lọc dữ liệu trên báo biểu, sử dụng thuộc tính RecordSelectionFormula với cú pháp:
Cú pháp:

<CrystalReport>.RecordSelectionFormula = _
"{<Tên bảng>.<Tên field>} <Toán tử so sánh> <Giá trị>"

<Toán tử so sánh> có thể là =, >=, <=, >, <, <>, In (<danh sách>), Not In (<danh sách>), In <giá
trị đầu> To <giá trị cuối>
<Giá trị> cần phải có ký hiệu của kiểu dữ liệu như ['] cho kiểu String, [#] cho kiểu DateTime
Hoặc sử dụng thuộc tính SelectionFormula của điều khiển hiển thị báo biểu CrystalReportViewer
Cú pháp:

<CrystalReportViewer>.SelectionFormula = _
"{<Tên bảng>.<Tên field>} <Toán tử so sánh> <Giá trị>"

II.6. Truyền tham số cho báo biểu


Để truyền tham số cho báo biểu, sử dụng phương thức SetParameterValue của báo biểu theo cú pháp
sau:
Cú pháp:

<CrystalReport>.SetParameterValue(<Tên tham số>, <Giá trị>)

<Tên tham số> là tên của tham số (ParameterField) đã tạo trong báo biểu.
<Giá trị> không cần có ký hiệu của kiểu dữ liệu.

II.7. Các loại kết xuất báo biểu


Mặc định, báo biểu được kết xuất ra màn hình, chúng ta có thể xuất báo biểu ra máy in hoặc tập tin
theo cú pháp sau:

II.7.1. Kết xuất ra máy in


Cú pháp:

<CrystalReport>.PrintToPrinter(<số bản>, <Collate>, _


<từ trang>, <đến trang>)

II.7.2. Kết xuất ra tập tin


Cú pháp:

<CrystalReport>.ExportToDisk(<loại tập tin>, <tên tập tin>)

<loại tập tin> có thể có các giá trị sau:

Học phần 3 – VB.NET Trang 175/187


Tài liệu hướng dẫn giảng dạy

Các gía trị thuộc tính của CrystalDecisions.[Shared].ExportFormatType (loại tập tin)
Giá trị Mô tả
Excel Xuất ra tập tin .XLS.
HTML40 Xuất ra tập tin HTML4.0
NoFormat Xuất ra tập tin không kiểu.
PortableDocFormat Xuất ra tập tin .PDF.
RichText xuất ra tập tin .RTF
WordForWindows xuất ra tập tin .DOC

Học phần 3 – VB.NET Trang 176/187


Tài liệu hướng dẫn giảng dạy

ĐỀ THI MẪU CUỐI HỌC PHẦN


Lập Trình Quản Lý (VB.NET)
Thời gian: 60 phút
Ngày thi:
*** Các kết quả lưu vào đĩa làm việc để chấm điểm ***

Phần I: Các thành phần cung cấp sẵn


1. Cơ sở dữ liệu
ƒ Mô tả
Đơn vị ABC có nhiều phòng ban với các nhân viên trực thuộc. Do nhu cầu công tác, nhân viên có thể
được điều động từ phòng ban này sang phòng ban khác. Viết chương trình tra cứu thông tin nhân viên.
ƒ Quan hệ giữa các bảng

2. Cấu trúc thư mục tổ chức ứng dụng

Thư mục Ý nghĩa


Bao_cao Chứa tập tin báo biểu BC_QUA_TRINH.rpt.rpt sử dụng trong ứng dụng
Du_lieu Chứa tập tin cơ sở dữ liệu QL_NHAN_SU.mdb
Lop_xu_ly_luu_tru Chứa XL_BANG.vb là lớp xử lý lưu trữ của ứng dụng
Lop_xu_ly_nghiep_vu Chứa các lớp xử lý nghiệp vụ của ứng dụng
Man_hinh Chứa tập tin màn hình MH_TRA_CUU.vb sử dụng trong ứng dụng

3. Danh sách các lớp xử lý

Lớp xử lý Ý nghĩa
XL_BANG.vb Lớp đối tượng đọc ghi dữ liệu và một số chức năng khác
XL_<Nghiệp vụ>.vb Các lớp xử lý nghiệp vụ kế thừa từ lớp bảng ứng với mỗi bảng trong CSDL

4. Danh sách các đối tượng thể hiện

Thể hiện Ý nghĩa


MH_TRA_CUU.vb Màn hình cho phép thực hiện chức năng tra cứu thông tin nhân viên
BC_QUA_TRINH.rpt Báo biểu xuất thông tin quá trình công tác của nhân viên

Học phần 3 – VB.NET Trang 177/187


Tài liệu hướng dẫn giảng dạy

5. MH_TRA_CUU.vb

Màn hình Tra cứu thông tin


Màn hình MH_TRA_CUU đã được cài đặt để:
ƒ Liệt kê ra danh sách chọn Thuộc phòng những phòng ban trong đơn vị.
ƒ Lưới đã được thiết kế để hiển thị dữ liệu tìm thấy (không cho chỉnh sửa).
ƒ Có thủ tục xuất dữ liệu ra lưới

6. BC_QUA_TRINH.rpt
Báo biểu đã được thiết kế để hiển thị thông tin như hình:

Báo biểu BC_QUA_TRINH.rpt được cung cấp

Học phần 3 – VB.NET Trang 178/187


Tài liệu hướng dẫn giảng dạy

Phần II: Các yêu cầu phải thực hiện


1. Bổ sung cho các lớp xử lý nghiệp vụ: (1 điểm)
Cài đặt để XL_NHAN_VIEN có thông tin của tên phòng dựa trên MPH, cột hiển thị Nam/Nữ dựa trên Nam

2. Cài đặt cho màn hình MH_TRA_CUU: ( 7 điểm)


ƒ Viết hàm Lap_bieu_thuc_loc() As String trả về điều kiện lọc dữ liệu dựa vào các giá trị trên màn hình có
nội dung sau: (cộng chung 6.5 điểm)
+ Nếu Họ có chứa khác rỗng, lọc theo điều kiện họ nhân viên có chứa nội dung (Like ) trên điều khiển,
ngược lại không lọc theo họ nhân viên (0.5 điểm)
+ Nếu Tên có chứa khác rỗng, lọc theo điều kiện tên nhân viên có chứa nội dung trên điều khiển,
ngược lại không lọc theo tên nhân viên (0.5 điểm)
+ Giới tính lọc theo điều kiện trên màn hình: (Nam), (Nữ) hoặc không lọc nếu (Nam Nữ) được chọn.
(0.5 điểm)
+ Nếu Thuộc phòng rỗng, không lọc theo phòng ban, ngược lại lọc theo phòng được chọn (0.5 điểm)
+ Lọc theo hệ số lương: (1.25 điểm với điểm chi tiết như mô tả bên dưới)
− Nếu hệ số lương từ, đến đều rỗng: không lọc
− Nếu hệ số lương từ khác rỗng và hệ số lương đến rỗng: lọc theo hệ số lương >= hệ số lương từ
− Nếu hệ số lương từ rỗng và hệ số lương đến khác rỗng: lọc theo hệ số lương <= hệ số lương
đến.
− Ngược lại, lọc ra hệ số lương trong đoạn hệ số lương từ đến hệ số lương đến
+ Lọc theo tuổi (dựa vào ngày sinh): (1.5 điểm với điểm chi tiết như mô tả bên dưới)
− Nếu tuổi từ, đến đều rỗng: không lọc
− Nếu tuổi từ khác rỗng và tuổi đến rỗng: lọc theo tuổi >= tuổi từ
− Nếu tuổi từ rỗng và tuổi đến khác rỗng: lọc theo tuổi <= tuổi đến
− Ngược lại, lọc ra tuổi trong đoạn tuổi từ đến tuổi đến
+ Không yêu cầu kiểm tra giá trị hệ số lượng, tuổi đến lớn hơn giá trị hệ số lương, tuổi từ.
+ Kết hợp các điều kiện lọc lại thành chuỗi lọc và trả về giả trị chuỗi lọc (0.5 điểm)
ƒ Nhấn nút lệnh Tra cứu, thực hiện các yêu cầu sau: (chung 0.75 điểm)
+ Lập dữ liệu nhân viên theo yêu cầu tra cứu trên màn hình (nội dung của hàm Lap_bieu_thuc_loc)
+ Xuất dữ liệu ra lưới Kết quả tìm kiếm
ƒ Bổ sung các đối tượng thích hợp để khi nhấn nút lệnh Xuất In, xuất báo biểu BC_QUA_TRINH.rpt lọc theo
nhân viên hiện hành trên lưới Kết quả tìm kiếm (1 điểm)

3. Xử lý trên báo biểu: (2 điểm)


ƒ Bổ sung tên phòng vào tiêu đề hồ sơ nhân viên như hình bằng chữ HOA (0.5 điểm)
ƒ Hiển thị họ tên trong cùng một field như hình (0.5 điểm)
ƒ Đánh số thứ tự các lần thuyên chuyển như hình (0.5 điểm)
ƒ Định dạng ngày sinh và ngày thuyên chuyển như hình: ngày tháng năm (0.5 điểm)

Học phần 3 – VB.NET Trang 179/187


Tài liệu hướng dẫn giảng dạy

Báo biểu BC_QUA_TRINH.rpt đã bổ sung theo yêu cầu

Học phần 3 – VB.NET Trang 180/187


Tài liệu hướng dẫn giảng dạy

ĐỀ THI MẪU KIỂM TRA CHUYÊN MÔN GIÁO VIÊN


Đề thi kiểm tra chuyên môn giáo viên:

LẬP TRÌNH QUẢN LÝ (VB.NET)


Thời gian: 150 phút

Phần lý thuyết (30 phút)

Câu 1. Biến khai báo trong VB.NET thuộc loại nào dưới đây:
a) Value Type, Pointer Type
b) Value Type, Reference Type
c) Pointer Type, Reference Type
d) Pointer Type, Reference Type, Value Type
Câu 2. Giả sử khai báo biến d có kiểu ngày:
Dim d As Date
d = Now
Hãy cho biết câu lệnh nào sau đây sẽ in ra ngày hiện hành theo dạng ngày tháng năm:
a) Msgbox (d.Date)
b) MsgBox (d.ToString(“dd/mm/yyyy”))
c) MsgBox (d.ToString(“dd/MM/yyyy”))
d) MsgBox (d.ToShortDateString())
Câu 3. Chọn lý do khai báo thủ tục sau đây bị lỗi:
Private Sub TEST(ByVal a As Integer, ByVal b As Integer, Optional ByVal c As Boolean )
' các lệnh
End Sub
a) Lỗi vì thiếu kiểu dữ liệu của thủ tục
b) Lỗi vì từ khóa ByVal của các tham số
c) Lỗi vì tham số Optional không có giá trị mặc định
d) Lỗi vì thừa từ ByVal trong Optional ByVal.
Câu 4. Tính chất nào sau đây không thuộc các tính chất của Lập trình hướng đối tượng:
a) Tính Cụ thể (Concret) c) Tính Bảo bọc (Encapsulation)
b) Tính Đa hình (Polymorphism) d) Tính Kế thừa (Inheritance)
Câu 5. Có các dòng lệnh sau:
Public … Property <Ten thuoc tinh>
Get
' Trả về giá trị
End Get
End Property
Chọn từ khóa thích hợp để điền vào phần … của thuộc tính:
a) MustOverride c) WriteOnly
b) ReadOnly d) ReadWrite
Câu 6. Từ khóa Shared trong khai báo các thành phần cho biết thành phần đó:
a) Được sử dụng chung giữa các đối tượng thuộc lớp đó
b) Có thể sử dụng thành phần Shared thông qua tên lớp
c) Có thể sử dụng thành phần Shared thông qua một biến thuộc lớp đó, ngay cả khi chưa cấp phát vùng
nhớ cho biến.
d) Từ khóa Shared hàm ý tất cả các câu trên.
Câu 7. Các thành phần được khai báo với từ khóa Protected cho phép truy xuất:
a) Chỉ trong chính lớp nơi thành phần đó được khai báo
b) Trong chính lớp nơi thành phần đó được khai báo và trong các lớp kế thừa từ lớp đó
c) Chỉ trong chính lớp nơi thành phần đó được khai báo và trong các thể hiện của lớp đó.

Học phần 3 – VB.NET Trang 181/187


Tài liệu hướng dẫn giảng dạy

d) Chỉ trong chính lớp nơi thành phần đó được khai báo và trong lớp cha của lớp đó.
Câu 8. Để tạo ra một đối tượng OleDbDataReader, chúng ta sử dụng cách nào sau đây:
a) Dim bo_doc As New System.OleDb.OleDbDataReader
b) ' với Lenh là đối tượng OleDbCommand đã tạo sẵn
Dim bo_doc As System.OleDb.OleDbDataReader = Lenh.ExecuteReader()
c) ' với Lenh là đối tượng OleDbCommand đã tạo sẵn
Dim bo_doc As System.OleDb.OleDbDataReader = Lenh.ExecuteDataReader()
d) Các câu a, b đúng
Câu 9. Cho bảng dữ liệu như sau:
CONG_VIEC
MCV Ten_cong_viec Don_vi_tinh Don_gia
1 Đào móng đất cấp 3 M3 20000
2 Đổ bê tông 4x6 M3 22000
3 Đổ bê tông 1x2 M3 35000
4 Xây tường 10 M2 10000
5 Xây tường 20 M3 25000
6 Đổ đất nền M3 10000
7 Đóng cốp pha M2 25000
8 Lót gạch men M2 30000
Cho biết biến ketqua chứa giá trị nào khi thực hiện đoạn lệnh sau đây. Biết rằng Ket_noi là đối tượng
OleDbConnection đã kết đến nguồn dữ liệu cần thiết:
Dim Lenh As New System.OleDb.OleDbCommand("Select Ten_cong_viec From CONG_VIEC", _
Ket_noi)
Ket_noi.Open
Dim ketqua = Lenh.ExecuteScalar()
Ket_noi.Close
a) "Đào móng đất cấp 3" c) "Đào móng đất cấp 3, Đổ bê tông 4x6,
b) "Lót gạch men" …, Lót gạch men"
d) Chương trình bị lỗi
Câu 10. Đối tượng OleDbCommandBuilder được dùng để ?
a) Khai báo các OleDbCommand
b) Phát sinh ra OleDbDataAdapter
c) Phát sinh ra SelectCommand của OleDbDataAdapter
d) Phát sinh ra các DeleteCommand, InsertCommand và UpdateCommand của OleDbDataAdapter dựa
trên SelectCommand của nó
Câu 11. Cho bảng NHAN_VIEN có cấu trúc sau:
Field Name Field Type Field Size Description
MNV Autonumber Long Integer Mã nhân viên
Ho_ten Text 50 Họ tên nhân viên
Gioi_tinh Yes/No Giới tính: Yes: Nam ; No: Nữ
Ngay_sinh Date/Time Ngày sinh
Dia_chi Text 50 Địa chỉ
Với Mo_ket_noi là hàm trả về OleDbConnection kết nối đến CSDL chứa bảng NHAN_VIEN nói trên
Xét các câu lệnh sau:
(1) Dim bo_doc_ghi As New OleDbDataAdapter("Select Ho_ten, Gioi_tinh, Ngay_sinh, Dia_chi " _
& "From NHAN_VIEN", Mo_ket_noi)
(2) Dim bo_phat_sinh As New OleDbCommandBuilder(bo_doc_ghi)
Khi thực hiện, bo_phat_sinh sẽ không phát sinh được các lệnh DeleteCommand, InsertCommand và
UpdateCommand vì:
a) Dòng lệnh khai báo (2) thiếu tham số
b) OleDbCommandBuilder không phải là đối tượng phát sinh các Command còn lại
c) Nội dung SelectCommand của OleDbDataAdapter không có cột khóa chính hoặc cột duy nhất
d) Nội dung SelectCommand của OleDbDataAdapter không phải từ hai bảng trở lên

Học phần 3 – VB.NET Trang 182/187


Tài liệu hướng dẫn giảng dạy

Câu 12. Cho cấu trúc dữ liệu như sau:

Với bang_to_xay_dung là DataTable chứa dữ liệu đọc về từ TO_XAY_DUNG


bang_tho là DataTable chứa dữ liệu đọc về từ THO
Hai bảng này chưa thuộc về DataSet nào
Để tạo quan hệ giữa bang_to_xay_dung và bang_tho, sử dụng đoạn lệnh nào sau đây:
a) Dim quan_ly As New Dataset
Dim qh As New DataRelation("TO_THO", bang_to_xay_dung.Columns("MTO"), _
bang_tho.Columns("MTO"))
quan_ly.Relations.Add(qh)
b) Dim quan_ly As New Dataset
quan_ly.Tables.AddRange(New DataTable(){bang_tho, bang})
Dim qh As New DataRelation("TO_THO", bang_to_xay_dung.Columns("MTO"), _
bang_tho.Columns("MTO"))
c) Dim quan_ly As New Dataset
quan_ly.Tables.AddRange(New DataTable(){bang, bang_tho})
Dim qh As New DataRelation("TO_THO", bang_tho.Columns("MTO"), _
bang_to_xay_dung.Columns("MTO")))
quan_ly.Relations.Add(qh)
d) Dim quan_ly As New Dataset
quan_ly.Tables.AddRange(New DataTable(){bang_tho, bang})
Dim qh As New DataRelation("TO_THO", bang_to_xay_dung.Columns("MTO"), _
bang_tho.Columns("MTO"))
quan_ly.Relations.Add(qh)
Câu 13. DataTable bang_chi_tiet có các DataColumn như sau: MHD, MHH, So_luong, Don_gia với ý nghĩa Mã
hóa đơn kiểu Integer, Mã hàng hóa kiểu Integer, Số lượng kiểu Integer, Đơn giá kiểu Integer.
Để tính toán trị giá của một mã hóa đơn M có thể sử dụng cú pháp nào dưới đây:
a) Compute( Sum(So_luong*Don_gia) )
b) Compute( "Sum(So_luong*Don_gia)", "MHD=" & M)
c) Compute( "Sum(So_luong*Don_gia)", "Where MHD =" & M)
d) Không thể sử dụng cú pháp nào ở trên
Câu 14. Các phát biểu nào sau đây về DataView được xem là SAI: (chọn 2 câu)
a) Một DataTable có thể tạo ra nhiều DataView
b) Không thể cập nhật cho DataView
c) Có thể lọc và sắp xếp dữ liệu trên DataView
d) Một DataView có thể được tạo ra từ nhiều DataTable
Câu 15. Sử dụng đoạn lệnh nào sau đây để tạo cột tự động tăng STT trên DataTable bang:
a) bang.Columns.Add("STT", Type.GetType("System.Integer"), "AutoIncrement")
b) bang.Columns.Add("STT", Type.GetType("System.Integer"), "AutoIncrement=True")
c) bang.Columns.Add("STT", Type.GetType("System.Integer"), "Identity=True")
d) Dim cot As DataColumn= bang.Columns.Add("STT", Type.GetType("System.Integer"))
cot.AutoIncrement = True
Câu 16. Giữa hai DataTable bang_hoa_don (bảng một) và bang_chi_tiet (bảng nhiều) có một quan hệ
(DataRelation) tên "HD_CT" thông qua cột "MHD". Chọn hai cách tạo cột cho bang_hoa_don thể hiện
số mặt hàng được bán qua mỗi hóa đơn:
a) bang_hoa_don.Columns.Add("So_mat_hang", System.Integer, "Count(Child.MHD)")
b) bang_hoa_don.Columns.Add("So_mat_hang", Type.GetType("System.Integer"), _
"Count(Child.MHD)")

Học phần 3 – VB.NET Trang 183/187


Tài liệu hướng dẫn giảng dạy

c) bang_hoa_don.Columns.Add("So_mat_hang", Type.GetType(System.Integer), _
"Count(Child.MHD)")
d) bang_hoa_don.Columns.Add("So_mat_hang", Type.GetType("System.Integer"), _
"Count(Child(HD_CT).MHD)")
Câu 17. Thuộc tính RowState của DataRow có các giá trị nào sau đây:
a) Added, Deleted, Detached, Modified, Unchanged
b) Added, Deleted, Modified, Unchanged
c) Added, Deleted, Modified Original, Modified Current, Unchanged
d) Deleted, EditAdd, EditInProgress, Unchanged
Câu 18. Khai báo nào sau đây không hợp lệ trên phần General:
a) Const Chuoi_vi_tri = "\..\Du_lieu\CSDL.mdb"
b) Const Chuoi_vi_tri As String= "\..\Du_lieu\CSDL.mdb"
c) Const Chuoi_vi_tri As String= Application.StartUpPath & "\..\Du_lieu\CSDL.mdb"
d) Private Chuoi_vi_tri As String= Application.StartUpPath & "\..\Du_lieu\CSDL.mdb"
Câu 19. Date.Today trả về giá trị của ngày hiện hành. Trên một máy tính có Region Settings qui định cách hiển
thị ngày tháng năm là dd/MM/yyyy, trên Immediate Window, kết quả nào sau đây được in ra khi thực
hiện dòng lệnh :
?Date.Today (giả sử có trị ngày 15 tháng 6 năm 2005)
a) #15/06/2005# c) #6/15/2005#
b) #15/06/2005 12:00:00# d) #06/15/2005#
Câu 20. Phương thức AddNew của DataView trả về một DataRowView và khi được gọi số dòng trên DataView
(<Dataview>.Count) tăng thêm một. Trên DataTable mà DataView được tạo, số dòng
(<DataTable>.Rows.Count) sẽ:
a) Bằng số dòng trên DataView
b) Bằng số dòng trên DataView có tình trạng là DataViewRowState.CurrentRows
c) Không thay đổi so với số dòng trên DataTable trước khi AddNew của DataView được gọi
d) Các câu trên đều sai
Câu 21. Xét đoạn lệnh sau trên DataTable bang_nv:
Dim a,b As Integer
a = bang_nv.Rows.Count
bang_nv.Rows(0).Delete()
b = bang_nv.Rows.Count
Hãy cho biết a và b thế nào sau khi thực hiện thành công đoạn lệnh trên (không bị lỗi)

a) a<b
b) a=b
c) a>b
d) a=b+1

Câu 22. Để xuất dữ liệu liệt kê ra điều khiển ComboBox, khi sử dụng đoạn lệnh sau:
<ComboBox>.DisplayMember = "<tên cột hiển thị>"
<ComboBox>.ValueMember = "<tên cột lưu trữ>"
<ComboBox>.DataSource = <DataTable>
Người ta thấy các dòng trên ComboBox hiển thị cùng nội dung là "System.Data.DataRowView"
Hãy chọn giải thích đúng cho trường hợp này
a) <tên cột hiển thị> không có trên <DataTable>
b) <tên cột lưu trữ> không có trên <DataTable>
c) <ComboBox>.DataSource phải sửa lại là <ComboBox>.RowSource
d) Các giải thích trên đều sai
Câu 23. Để gọi thực hiện báo biều Crystal Report BC_NHAN_VIEN, sử dụng đoạn lệnh nào sau đây:
a) Dim bb As New BC_NHAN_VIEN
bb.Show

Học phần 3 – VB.NET Trang 184/187


Tài liệu hướng dẫn giảng dạy

b) Dim bb As New BC_NHAN_VIEN


Dim crv As New CrystalDecisions.Windows.Forms.CrystalReportViewer
crv.ReportSource = bb
crv.Show
c) Dim bb As New BC_NHAN_VIEN
Dim crv As New CrystalDecisions.Windows.Forms.CrystalReportViewer
crv.ReportSource = bb
crv.PrintReport
d) Các câu trên đều sai
Câu 24. Trong mô hình PUSH của Crystal Report, dữ liệu xuất trên báo biểu:
a) Do .Net FrameWork xử lý đọc về.
b) Do người lập trình viết lệnh đọc dữ liệu và gửi lên cho báo biểu.
c) Do Crystal Report tự đọc về qua việc khai báo các bảng và thông tin kết nối khi thiết kế báo biểu
d) Các câu trên đều sai
Câu 25. Để truyền giá trị cho tham số Ngay_sinh cho báo biểu Crystal Report BC_NHAN_VIEN, sử dụng cú
pháp nào dưới đây:
a) Dim bb As New BC_NHAN_VIEN
Dim ngay As New Date(1988,1,1)
bb.ParameterFields(0) = ngay
b) Dim bb As New BC_NHAN_VIEN
Dim ngay As New Date(1988,1,1)
bb.SetParameterValue("Ngay_sinh", ngay)
c) Dim bb As New BC_NHAN_VIEN
Dim ngay As New Date(1988,1,1)
bb.ParameterFields.Add( ngay)
d) Các câu trên đều đúng

Học phần 3 – VB.NET Trang 185/187


Tài liệu hướng dẫn giảng dạy

Phần thực hành (120 phút)

I. Tạo CSDL
a) Mô tả
Vào mỗi cuối tháng, công ty xây dựng ABC dựa trên bảng chấm công và lương của các tổ xây dựng để
tính lương cho thợ. Mỗi tổ trưởng, ngoài phần lương của mình còn nhận được khoản phụ cấp trách nhiểm
trích từ lợi nhuận của công ty.
b) Cấu trúc các bảng
Tập tin cơ sở dữ liệu QL_LUONG.mdb gồm các bảng : (các field in đậm và gạch dưới là khóa chính)

TO_XAY_DUNG – Danh saùch caùc toå xaây döïng


Field Name Field Type Field Size Description
MTO Autonumber Long Integer Maõ toå xaây döïng
Ten_to Text 30 Teân toå xaây döïng
To_truong Number Long Integer Maõ thôï laø toå tröôûng

THO – Danh saùch thôï


Field Name Field Type Field Size Description
MTH Autonumber Long Integer Maõ thôï
Ho_ten Text 30 Hoï teân thôï
Gioi_tinh Yes/No Giôùi tính: Yes: Nam ; No: Nöõ
Ngay_sinh Date/Time Ngaøy sinh
HSL Number Single Heä soá löông
MTO Number Long Integer Maõ toå xaây döïng

CHAM_CONG – Chaám coâng thôï


Field Name Field Type Field Size Description
MCC Autonumber Long Integer Maõ chaám coâng
MTH Number Long Integer Maõ thôï
Ngay_nghi Date/Time Ngaøy nghæ

LUONG_TO – Löông thaùng cuûa caùc toå xaây döïng


Field Name Field Type Field Size Description
MLG Autonumber Long Integer Maõ löông toå
MTO Number Long Integer Maõ toå xaây döïng
Nam_thang Text 6 Naêm thaùng tính löông
Tong_luong Number Double Löông thaùng cuûa toå

LUONG – Löông thaùng cuûa thôï


Field Name Field Type Field Size Description
STT Autonumber Long Integer Soá thöù töï löông
MLG Number Long Integer Maõ löông toå
MTH Number Long Integer Maõ thôï
So_cong Number Integer Soá ngaøy coâng
Phu_cap Number Long Integer Phuï caáp traùch nhieäm
Tien_luong Number Long Integer Tieàn löông thaùng

Học phần 3 – VB.NET Trang 186/187


Tài liệu hướng dẫn giảng dạy

c) Quan hệ giữa các bảng

Hình 1 – Quan hệ giữa các bảng


II. Các màn hình làm việc
a) Màn hình khởi động
Tạo form MDI với tiêu đề Quản lý lương có thực đơn như sau:

Hình 2 – Màn hình và các thành phần của hệ thống menu

Khi người dùng chọn các mục trong menu, thực hiện các yêu cầu tương ứng sau:
o Giới thiệu: dùng MsgBox hiển thị thông tin của thí sinh: Họ tên – Năm sinh
o Chọn thời gian: Hiển thị màn hình chọn thời gian câu 2 ở chế độ hộp thoại.
o Đóng: Hiển thị cửa sổ thông báo “Ứng dụng sẽ đóng lại. Bạn có đồng ý không ?”. Tùy theo trả lời của
người dùng, sẽ thực hiện đóng ứng dụng hay không (Có thể sử dụng hàm MsgBox).
o Tính lương: Hiển thị màn hình câu 3
Khi mở màn hình này mặc nhiên mở luôn màn hình chọn thời gian câu 2 ở chế độ hộp thoại

b) Màn hình thời gian


Thiết kế một màn hình cho phép xác định thời gian làm việc và ghi nhận lại thời gian này:

Hình 3 – Màn hình chọn thời gian làm việc


o Tháng liệt kê các tháng trong năm (bằng chữ)
o Năm liệt kê các năm từ 2000 đến 2010
o Nút Chọn: xác nhận thời gian chọn và đóng màn hình lại

c) Màn hình tính lương


Thiết kế một màn hình cho phép cập nhật số công và thực hiện tính lương:

Học phần 3 – VB.NET Trang 187/187


Tài liệu hướng dẫn giảng dạy

Hình 4 – Màn hình tính lương

o Tiêu đề hiển thị "Tính lương tháng" <tháng làm việc> " năm " <năm làm việc>
o Điều khiển Tổ liệt kê các tổ xây dựng.
o Khi chọn một tổ xây dựng, Tổng lương hiển thị lương của tổ trong năm tháng làm việc, thực hiện các
yêu cầu sau:
o Nếu lương tổ > 0, lưới hiển thị thông tin tính lương của các thợ trong tổ được chọn ứng với năm tháng
làm việc nếu có. Nếu trong CSDL chưa có, cần phát sinh thông tin cho tổ được chọn ứng với năm
tháng làm việc.
o Nếu không tồn tại lương tổ được chọn, lưới sẽ không hiển thị.
o Cập nhật công cho phép cập nhật số công của thợ ứng với năm tháng làm việc:
Số công = số ngày trong tháng năm tính lương - số ngày nghỉ trong tháng
o Chia lương: thực hiện các bước:
o Xác định đơn vị lương của tổ được chọn = Tổng lương / Tổng(số công *HSL) của các thợ trong tổ
o Cập nhật cột Tien_luong = đơn vị lương * Số công * HSL cho các thợ trong tổ . Nếu là tổ trưởng, cập
nhật thêm cột Phu_cap = Tien_luong*0.05
o In phiếu lương: xuất báo biểu phiếu lương các thợ trong tổ được chọn ứng với năm tháng làm việc

III. Báo biểu


Thiết kế báo biểu sau:

…các thợ khác trong tổ


Hình 5 – Báo biểu của câu 3

Học phần 3 – VB.NET Trang 188/187

You might also like