24/05/2018, 15:09

Truy cập cơ sở dữ liệu với lớp

Các ứng dụng truy cập dữ liệu thường phức tạp hơn nhiều so với các ứng dụng thông thường. Lý do Visual Basic đưa ra các công nghệ DAO, ADO, ODBC là nhằm giúp giải quyết tính phức tạp này. Nhưng các công nghệ này chỉ mới giải quyết những phức tạp nảy ...

Các ứng dụng truy cập dữ liệu thường phức tạp hơn nhiều so với các ứng dụng thông thường. Lý do Visual Basic đưa ra các công nghệ DAO, ADO, ODBC là nhằm giúp giải quyết tính phức tạp này.

Nhưng các công nghệ này chỉ mới giải quyết những phức tạp nảy sinh trong quá trình phát triển phần mềm. Mô hình đối tượng cơ sở dữ liệu như ADO chẳng hạn, giúp ta trừu tượng hoá cơ sở dữ liệu và do đó tạo sự dễ dàng khi cập nhật một bản ghi hoặc sửa đổi định nghĩa bảng trong chương trình. Tuy nhiên, nó không giúp ta tính thuế trên doanh thu bán hàng hay từ chối một mẩu dữ liệu khách hàng bởi vì nó không có ID hợp lệ.

Visual Basic cho phép ứng dụng củng cố các quy luật kinh doanh vào các lớp. Lớp là một kiểu mô – dun chương trình cho phép ta tạo đối tượng. Các đối tượng ta tạo với mô-dun lớp tương tự các đối tượng truy cập dữ liệu ta sử dụng để giao tiếp với cơ sở dữ liệu, ngoại trừ chúng được dùng cho mục đích bất kỳ. Trong ngữ cảnh truy cập cơ sở dữ liệu, ta chú yếu dùng lớp cùng với các đối tượng cơ sở dữ liệu để tạo nên một ứng dụng truy cập cơ sở dữ liệu.

Giả sử ta tạo một ứng dụng xử lý hoá đơn và khách hàng. Trong một ứng dụng không theo hướng đối tượng, ta phải viết các hàm hay thủ tục ghi thông tin khách hàng và hoá đơn, trả về các thông tin từ cơ sở dữ liệu, in thông tin, v.v.. Nếu viết bằng Visual Basic, ta còn phải xử lý rải rác trên hàng chục thủ tục sự kiện.

Là người lập trình theo hướng đối tượng, ta sẽ bắt đầu bằng cách phân tích và thiết kế các thành phần, hay là đối tượng khái quát hoá vấn đề xử lý khách hàng và hoá đơn. Anh ta hay cô ta sẽ xác định một đối tượng khách hàng có những thông tin gì và đối tượng khách hàng đó có thể thực hiện những hành động nào trên dữ liệu; tương tự với đối tượng hoá đơn. Sau khi đối tượng được phân tích và thể hiện thành lớp, nó sẽ được sử dụng trong ứng dụng. Ta có thể dùng lại đối tượng khách hàng và đối tượng hoá đơn trong ứng dụng bất kỳ sau này. Bởi vì mã nguồn của đối tượng tồn tại trong nơi chứa rất dễ truy cập đến là mô-dun lơp thay vì trong rất nhiều thủ tục sự kiện rải khắp ứng dụng, ta cũng có thể dễ dàng gỡ rối và bảo trì các đối tượng này.

Ngoài ra, lớp và đối tượng còn tận dụng các tính năng ngôn ngữ mạnh của Visual Basic. Ví dụ, có một quan hệ giữa khách hàng và hoá đơn – ta có thể nói một khách hàng thuộc về một hoá đơn, hay chính xác hơn, tập hợp các hoá đơn thuộc về một khách hàng. Visual Basic hỗ trợ tập hợp các đối tượng.

Một hệ thống hướng đối tượng có 3 đặc điểm :

- Trừu tượng h: rút gọn vấn đề đến mức dễ hiểu nhất.

- Đa hình:cho phép đối tượng thi hành cùng phương thức và chứa cùng dữ liệu với các đối tượng khác. Điều này tạo sự dễ dàng khi lập trình, giúp ta không cần xử lý lại với từng đối tượng, bởi vì các đối tượng vẫn có cùng phương thức và thuộc tính.

- Tóm lược:đây là cơ chế qua đó logic chương trình và dữ liệu được nhóm lại với nhau.

- Kế thừa :đối tượng hiện hữu có thể sinh ra một đối tượng mới. Tính năng này trong Visual Basic còn bị hạn chế, nó được cung cấp dưới dạng các giao diện và thông qua đại diện.

Bạn nên xem lại chương 2 : Tìm hiều Visual Basic và chương 10 : Lập trình hướng đối tượng.

Tạo cây phân nhánh lớp với tiện ích xây dựng lớp

Khi ta thiết kế lớp chứa lớp, nhất là lớp có tập hợp – chương trình trở nên khó viết vì rất khó quản lý chúng. Tiện ích xây dng lớp (ClassBuilderutility) giúp ta thiết lập và quản lý các quan hệ giữa tập hợp các lớp bao bọc chúng dễ dàng hơn.

Tạo một lớp tập hợp cho phép làm việc với tập hợp của đối tượng Order

1. Khởi động Visual Basic và nạp đề án chứa lớp COrder.

2. Từ menu Add-Ins,chọn Add-Ins Manager.

3. Nhấn ClassBuilderUtility trong hộp thoại Add-InManager. Trong bảng Load

Behavior, nhấn Loaded/Unloaded.

4. Nhấn OK. Tiện ích xây dựng lớpđược nạp và xuất hiện trên menu Add-Ins.

5. Để phóng tiện ích xây dựng lớp,chọn menu Add-Ins,Class Builder Utility

6. Tiện ích xây dựng lớp cảnh báo rằng đề án hiện hành chứa lớp hiện hành chưa được xây dựng với tiện ích này. Nhấn OK.

7. Cửa sổ Tiện ích xây dựng lớp xuất hiện.

: Dùng nút NewCollection(nút thứ hai từ trái sang) của tiện ích xây dựng lớp để tạo một lớp tập hợp.

8. Bây giờ, ta dùng Tiện ích xây dựng lớp để tạo lớp tập hợp. Nhấn nút AddNew

Collection trên thanh công cụ:

Nút Add New Collection

9. Hộp thoại CollectionBuilder xuất hiện. Trong ô Name, nhập tên của lớp tập hợp – colOrder.

10. Chọn COrder trong bảng có chữ “CollectionOf“.Điều này cho biết lớp tập hợp này là một tập hợp của đối tượng COrder. Nó tạo sự an toàn về kiểu cho lớp – khác với các tập hợp thông thường, chỉ đối tượng COrder mới được thêm vào tập hợp này.

11. Nhấn OK. Lớp tập hợp được thêm vào tiện ích xây dựng lớp.

12. Ta có thấy tiện ích xây dựng lớp phát sinh các thuộc tính và phương thức để hỗ trợ 4 phương thức của tập hợp (Add,Count,ItemRemove) cũng như là NewEnum.

Tiện ích xây dựng lớp tạo thuộc tính NewEnum cho phép lớp tập hợp hỗ trợ phép lặp xuyên qua tập hợp dùng cấu trúc điều khiển For Each..Next. Không nhất thiết phải dùng thuộc tính này trong chương trình, nhưng ta biết sẽ dùng nó với For Each..Next.

13. Bây giờ ta định nghĩa lớp tập hợp, ta có thể yêu cầu tiện ích xây dựng lớp phát sinh chương trình bằng chọn menu File Update Project hoặc dùng phím tắt Ctrl+S.

14. Tiện ích tự động xây dựng lớp tập hợp. Đóng tiện ích bằng cách chọn File, Exit.Ta thấy lớp Ordersđược tạo ra do tiện ích xây dựng lớp.

Ta cũng thấy rằng tiện ích đã định nghĩa lại cú pháp của phương thức Addcủa tập hợp. Thay vì lấy đối tượng làm tham biến như phương thức Addcủa tập hợp quy ước, phương thức Addmới lấy biến làm tham biến. Những biến này gắn với các thuộc tính của đối tượng COrder.Điều này cho phép ta tạo đối tượng, thêm nó vào tập hợp, gán giá trị cho nó - những cải tiến đáng kể so với cách thức thực hiện thông thường.

Dim MyOrder as COrder

Dim MyOrders as colOrder

Set MyOrders= New colOrder

set MyOrder= MyOrders.Add(2.99, "Cheese", 201, #6/5/99#)

Mặc dù vậy, đây chưa phải là cú pháp tốt nhất để thêm mộ phần tử vào tập hợp. Có thể dùng cách gọn gàng hơn:

Dim MyOrder as COrder
    Dim MyOrders as colOrder
    Set MyOrders= New colOrder set MyOrder= MyOrders.Add() MyOrder.Price = 2.99
    MyOrder.ItemOrdered = "Cheese" MyOrder.CustomerID = 201
    MyOrder.OrderDate = #6/5/99#
    

Cả hai cách đều đưa về cùng kết quả: một đối tượng được thêm vào tập hợp và thuộc tính được gán giá trị. Cách thứ hai, dùng thuộc tính thay vì tham biến trông rõ ràng, vì vậy ta sử dụng nó rộng rãi hơn.

Một trường hợp dùng tham biến thuận tiện hơn thuộc tính là khi lớp tập hợp tồn tại trong một thành phần triển khai từ xa qua mạng. Theo kịch bản đó, mỗi lần gọi đến thuộc tính là sinh ra một truy cập 2 lượt đi về qua mạng. Vì vậy, để ứng dụng hoạt động tốt hơn, ta nên dùng tham biến và chỉ gọi một lần.

Sửa đổi phương thức Add của lớp tập hợp để bỏ qua tham biến

Public Function Add(Optional sKey as String) as COrder
    Dim objNewMember as COrder
    Set objNewMember = New COrder
    If Len(sKey) =0 Then mCol.Add objNewMember Else
    mCol.Add objNewMember, sKey
    End If
    Set Add = objNewMember
    Set objNewMember = Nothing
    End Function
    

Dùng lớp tập hợp để thao tác với các phần tử dữ liệu

Để xây dựng ứng dụng dùng lớp COrdercolOrder, ta theo các bước sau :

1. Tạo đề án Standard Exe mới. Thêm lớp COrder colOrder.

2. Trong đề án, tạo một biểu mẫu cho phép người sử dụng đưa vào Date, CustomerID,Item,Price.Thêm 2 nút lệnh vào giao diện, nút thứ nhất nhập dữ liệu, trong khi nút thứ hai tính toán tổng số hoá đơn được nhập.

3. Trong biểu mẫu, khai báo 2 biến mức mô-dun, một cho đối tượng COrdervà một cho tập hợp colOrder.

Option Explicit
    Private ThisOrder as COrder
    Private AllOrders as colOrder
    

4. Tạo instance cho tập hợp colOrder trong sự kiện Load của biểu mẫu.

Private Sub Form_Load ()
    Set AllOrders = New colOrder
    End Sub
    

5. Viết chương trình cho sự kiện Clickcủa nút Add để thêm hoá đơn vào tập hợp, rồi khởi động lại giao diện người sử dụng của ứng dụng.

Private Sub cmdAdd_Click ()
    ‘ Creates a new order and adds
    ‘ it to the collection
    Set ThisOrder = AllOrders.Add
    ThisOrder.OrderDate = txtOrderDate.Text ThisOrder.CustomerID = txtCustomerID.Text ThisOrder.ItemOrdered = txtItemOrdered.Text ThisOrder.Price = txtPrice.Text
    ‘ Reset the user Interface txtOrderDate.Text = " " txtCustomerID.Text = " " txtItemOrdered.Text = " " txtPrice.Text = " " txtOrderDate.SetFocus
    End Sub
    

6. Sau cùng, trong sự kiện Click của nút Total, viết chương trình để trả về tổng số hoá đơn đã nhập dùng vòng lặp

For Each.. Next.
    Private Sub cmdTotal_Click() Dim curTotal As Currency
    For Each ThisOrder In AllOrders
    curTotal = curTotal + ThisOrder.Price
    Next
    MsgBox "The total is " & curTotal, vbInformation
    End Sub
    

Tham chiếu đến phần tử trong tập hợp

Dùng vòng lặp ForEach..Next để duyệt qua tập hợp không phải là cách duy nhất để làm việc với tập hợp. Sau khi thiết lập và đưa vào các đối tượng, ta có thể lấy ra phần tử từ tập hợp. Nếu thêm đối tượng vào tập hợp với một khoá hay giá trị chuỗi duy nhất, ta có thể lấy về đối tượng mà không không cần xác định vị trí của nó trong tập hợp - một ưu điểm so với mảng.

Ví dụ, Để lấy về hoá đơn thứ 4 trong tập hợp :

Set MyOrder = AllOrders(4)
    

Để tham chiếu đến thuộc tính của đối tượng Order thứ 4 trong tập hợp, ta truyền vào chỉ mục của tập hợp :

AllOrders(4).OrderDate = #6/5/98#

Dòng lệnh này hoạt động nhờ thủ tục mặc định của tập hợp trả về một tham chiếu đến phần tử được đánh số. Thủ tục mặc định này là phương thức Item. Vì là mặc định, nên ta không cần gọi nó một cách tường minh. Nếu không, có thể dùng:

AllOrders.Item(4).OrderDate= #6/5/98#
Phần tử đầu tiên trong tập hợp được đánh số 1, không có phần tử thứ 0. Nó cũng khách với tập hợp của các đối tượng Form hay Control trong Visual Basic; các tập hợp này đánh số từ 0. Như vậy, tập hợp do ta tự tạo được đánh số từ 1; trong khi tập hợp do Visual Basic tạo đánh số từ 0. Đây cũng là trường hợp của tập hợp các đối tượng truy cập dữ liệu, như là tập hộp TableDefs của đối tượng Database.

Để trả về một phần tử từ tập hợp sử dụng một khoá trước đó, ta phải thêm nó vào tập với một khoá. Để thực hiện điều này, truyền một chuỗi duy nhất cho phương thức

Add :

AllOrders.Add "ORD193").prive

Ta sẽ gặp thông báo lỗi nếu như chuỗi này không duy nhất. Để tham chiếu đến một thuộc tính của đối tượng này, ta dùng dòng lệnh :

MsgBox AllOrders ("ORD193").prive

Lưu ý rằng ta không dùng giá trị số cho khoá của một đối tượng, ngay cả khi ta truyền nó cho phương thức Adddưới dạng chuỗi. Bởi vì phương thức Itemcó thể trả về một đối tượng từ tập hợp bằng khoá hoặc bằng vị trí xếp thứ tự. Nếu phương thức Itemnhận số n, nó trả về phần tử thứ n trong tập hợp. Nếu nó nhận một chuỗi, nó trả về đối tượng với khoá là chuỗi đó. Mặc dù vậy, Nếu chuỗi có thể chuyển thành số, ta sẽ có nguy cơ gặp lỗi.

Sử dụng biểu mẫu như lớp

Tạo một Instance của biểu mẫu Login

1. Trong đề án của Visual Basic, nhấn nút phải chuột trên cửa sổ Project Explorer.

2. Từ menu bật ra, chọn Add.Chọn Form.

3. Hộp thoại Formxuất hiện. chọn biểu mẫu Login.

4. Trong hộp thoại Form,nhấn Open.Một biểu mẫu mới được tạo.

5. Trong cửa sổ Code,đưa vào các thủ tục thuộc tính :

Public Property Get UserName() As String
    UserName = txtUserName.Text
    End Property
    Public Property Let UserName(ByVal strNew As String)
    txtUserName.Text = strNew
    End Property
    Public Property Get Password() As String
    Password = txtPassword.Text
    End Property
    Public Property Let Password(ByVal strNew As String)
    txtPassword.Text = strNew
    End Property
    Public Sub Login()
    MsgBox "Logging in user " & UserName & "." End Sub
    

6. Biểu mẫu Login chuẩn của Visual Basic chưa chương trình trong sự kiện nhấn nút OK và Cancel để người sử dụng Login vào hệ thống. Xoá đoạn chương trình đó đi và thay bằng đoạn chương trình sau:

Private Sub cmdCancel_Click() Me.Hide
    End Sub
    Private Sub cmdOK_Click() UserName = txtUserName.Text Password = txtPassword.Text Login
    Me.Visible = False
    End Sub
    

Điều này sẽ tận dụng thế mạnh của các thuộc tính và phương thức hiệu chỉnh của chúng ta. Ngoài ra, Form này sẽ được ứng dụng rộng rãi trong ứng dụng “Clien/Server” sẽ được trình bày trong phần sau.

Ta có thể tạo instance bội (multipleinstance) cho biểu mẫu tương tự như việc tạo instance bội cho các đối tượng từ lớp. Mỗi instance sau đó của biểu mẫu có định danh riêng trong ứng dụng, với một bản sao của toàn bộ thuộc tính, phương thức, và các điều khiển giao diện người sử dụng chứa trong thiết kế gốc của biểu mẫu.

Tạo ra nhiều instancecho biểu mẫu Login của người sử dụng là vô nghĩa. Tuy nhiên, đối với các biểu mẫu khác, ta tạo ra instance bội là điều thường gặp như ví dụ sau cho thấy :

Dim f as frmMain
    Set f = New frmMain f.Show
    

Sử dụng lớp và đối tượng trong truy cập cơ sở dữ liệu

Có một số phương tiện giúp cho việc áp dụng kỹ thuật hướng đối tượng trong truy cập dữ liệu trong Visual Basic :

  • Gắn một bản ghi duy nhất với một đối tượng : Đây là kỹ thuật đơn giản nhất, không cần lập trình nhiều. Mỗi trường trong bản ghi trở thành một thuộc tính của đối tượng; lấy dữ liệu về từ cơ sở dữ liệu hay lưu dữ liệu vào cơ sở dữ liệu đều được xử lý qua đối tượng.
  • Uỷ nhiệm xử lý dữ liệu cho một đối tượng Recordsetchứa trong một đối tượng: Đây là kỹ thuật tốt nhất khi ta cần xử lý một số không giới hạn các bản ghi. Kỹ thuật này cũng dễ lập trình, bởi vì có nhiều chức năng quản lý được cung cấp sẵn trong các mô hình đối tượng được sử dụng (DAO hay RDO). Kỹ thuật đặc biệt hữu dụng khi ta dùng ADObởi vì ADOcung cấp khả năng ngắt kết nối với nguồn dữ liệu, cho phép ứng dụng Clientthao tác với dữ liệu không cần kết nối với Server. Bởi vì nhiều người sử dụng kết nối đồng thời là một điểm yếu của các máy tính Client/Server,ngắt kết nối có nghĩa là giải pháp sẽ linh hoạt hơn.
  • Gắn nhóm các bản ghi vào một tập hợp : Lập trình phức tạp hơn trường hợp gắn một bản ghi với một đối tượng, nhưng nó hữu dụng hơn trong trường hợp ta phải xử lý với nhóm các bản ghi có liên quan tại một thời điểm. Ta có thể gặp phải khó khăn liên quan đến khả năng hoạt động của ứng dụng nếu ta không cẩn thận giới hạn số bản ghi xử lý tại một thời điểm.
  • Chia truy cập dữ liệu giữa ClientServer: Kỹ thuật này thích hợp nhất khi ta cần đạt được khả năng linh hoạt và hiệu quả cao nhất trong ứng dụng. Nó liên quan đến việc chia Logic của tầng trung gian của ứng dụng thành 2 phần : thành phần phía server thi hành truy cập và trả về dữ liệu đến Clien và thành phần phía Client nhận kết quả này và gắn chúng vào các thuộc tính của đối tượng.

Các dụ còn lại trong chương sẽ đưa ra ý tưởng kỹ thuật nào sẽ phù hợp trong từng tình huống cụ thể.

Sử dụng các lớp xử lý bản ghi duy nhất

Lớp xử lý bản ghi trả về một bản ghi duy nhất từ cơ sở dữ liệu và đưa nó vào ứng dụng dưới dạng một đối tượng. Các trường trong bản ghi được trình bày như những thuộc tính của đối tượng. Bất kỳ hành động nào thi hành trên dữ liệu ( như là lưu dữ liệu về cơ sở dữ liệu, in ấn, hay tiến hành tính toán ) đều được trình bày như những phương thức của đối tượng xử lý bản ghi.

Để cho phép lớp điền giá trị cho thuộc tính, ta cung cấp cho nó một phương thức (đặt tên là GetData) thi hành truy vấn một bản ghi duy nhất trên cơ sở dữ liệu, nó dùng các trường trong bản ghi được trả về để điền giá trị vào thuộc tính của đối tượng.

Khi giao cho đối tượng vai trò lấy bản ghi về từ cơ sở dữ liệu, ta cần cung cấp cho đối tượng ID của bản ghi, thường là khoá chính này; phương thức GetDatacủa đối tượng sẽ dùng khoá chính này để lấy về bản ghi cần thiết.

Đối tượng cũng có thể có thêm phương thức Savecho phép người sử dụng của thành phần lưu bản ghi vào cơ sở dữ liệu.

Sử dụng lớp xử lý mảng(ARRAY-HANDLING CLASS)

Ta có thể tạo lớp truy vấn cơ sở dữ liệu, sau đó truyền dữ liệu về ứng dụng Client dưới dạng mảng. Ưu điểm của giải pháp này là nếu lớp xử lý mảng được biên dịch thành ActiveX Server DLL hay EXE, nó có thể tạo ứng dụng Client mà không đòi hỏi tham chiếu đến bộ máy của cơ sở dữ liệu. Tất cả những gì Client cần là một tham chiếu đến thành phần ActiveX server. Điều này làm cho ứng dụng Client tiêu tốn ít tài nguyên hơn; ứng dụng dễ phân phát và định cấu hình hơn.

Tạo một thành phần phía server trả về một mảng nghĩa là ứng dụng phía Client không cần duy trì kết nối liên tục đến server, giúp tăng cường tính linh hoạt của ứng dụng Client/Server.

Sử dụng phương thức xưởng sản suất(FACTORY METHOD)

Xưởng sản xuất đối tượng là một phương pháp tạo các đối tượng khác. Ta dùng Xưởng sản xuất đối tượng trong trường hợp một đối tượng giữ vai trò tạo ra các đối tượng khác. Để tạo ra các đối tượng khác, ta dùng phương thức; các phương thức này gọi là phương thức xưởng sản xuất.

Ví dụ, đối tượng Database của DAO,có một số phương thức xưởng sản xuất cung cấp đối tượng :

Phương thức Mô tả
CreateQueryDef Tạo một đối tượng QueryDef.
CreateRelation Tạo một đối tượng Relation
CreateTableDef Tạo một đối tượng TableDef
OpenRecordset Tạo một đối tượng Recordset
CreateProperty Tạo một đối tượng Property

Ngoài việc sử dụng các phương thức xưởng sản xuất do Visual Basic cung cấp, ta có thể tạo ra các phương thức này trong các lớp tự tạo.

Một lý do phổ biến để dùng các phương thức xưởng sản xuất là yêu cầu thực hiện theo cách tạo đối tượng trong Visual Basic. Các ngôn ngữ lập trình khác sử dụng đối tượng (như Visual C++) có contructor đảm nhiệm việc tạo Instance của đối tượng từ lớp; những constructor còn có thể thi hành các tác vụ khác, như cung cấp các dữ liệu khởi tạo cho lớp. Lớp có nhiều constructor để người lập trình có thể chọn lựa và constructor có thể lấy và trả về tham số.

Tuy nhiên, không có tương quan trực tiếp với constructor trong Visual Basic. Thay vào đó, các lớp Visual Basic có sự kiện Initialize. Ta có thể lập trình trong sự kiện Initializenhư trong constructor của Visual C++, nhưng không may là ta không thể truyền tham số cho sự kiện Initializecủa Visual Basic, và ta chỉ có một sự kiện Initialize cho mỗi lớp. Nó làm tính tiện dụng của sự kiện Initialize bị hạn chế đối với mọi phần tử, ngoại trừ các giá trị cơ bản nhất là các giá trị mặc định. Các phương thức xưởng sản xuất cung cấp giải pháp khắc phục điều này.

Option Explicit
    ' Requires CCustomer class
    Public Function CreateCustomer(Optional lngID As Variant) As CCustomer
    Dim Cust As CCustomer
    If IsMissing(lngID) Then
    ' Create new customer
    Set CreateCustomer = New CCustomer
    Else
    ' Retrieve customer from DB Set Cust = New CCustomer Cust.GetData (lngID)
    Set CreateCustomer = Cust
    End If
    End Function
    

Xưởng sản xuất đối tượng tạo một đối tượng khách hàng rất dễ dàng với đầy đủ tính năng. Đoạn chương trình sau tạo đối tượng CCustomer:

Dim MyCust As CCustomer
    Dim cf As CCustFactory
    Set cf = New CCustFactory
    ' Retrieve data
    Set MyCust = cf.CreateCustomer(txtID.Text)
    

Một lý do khách để dùng các phương thức xưởng sản xuất trong lập trình cơ sở dữ liệu Visual Basic là để tiết kiệm các tài nguyên kết nối, bởi kết nối đến cơ sở dữ liệu đòi hỏi tiêu tốn nhiều thời gian và bộ nhớ trên Client và Server.

Nếu dùng lớp xưởng sản xuất sẽ dễ dàng hạn chế số kết nối thực hiện với server. Ta chỉ kết nối một lần, trong lớp xưởng sản xuất thay vì trong mỗi mô-dun lớp.

Lớp có khả năng ràng buộc trực tiếp với cơ sở dữ liệu. Đây là tính năng mới trong Visual Basic 6.0. Ta không cần giới hạn các điều khiển dữ liệu thành nguồn dữ liệu cho ứng dụng cơ sở dữ liệu.

Ngoài việc cung cấp nguồn dữ liệu mới, Visual Basic 6 còn loại bỏ những hạn chế về cách thức kết nối của ứng dụng với nguồn dữ liệu. Ta không cần thiết lập ràng buộc dữ liệu vào lúc thiết kế, như với điều khiển DAO Data.Thay vào đó, ta có thể gán một nguồn dữ liệu (như là điều khiển ADOData, thiết kế DataEnvironment, hay lớp cung cấp dữ liệu ) cho phần tiêu thụ dữ liệu (như là một điều khiển giao diện nguời sử dụng ràng buộc ) lúc thi hành. Điều này cho phép đóng gói mô-dun lớp truy cập dữ liệu.

Để tạo một lớp làm nguồn dữ liệu truy cập cơ sở dữ liệu Novelty, ta theo các bước sau:

1. Tạo một đề án Standard EXE.

2. Dùng menu Project để thêm một mô-dun lớp vào đề án. Đặt tên mô-dun lớp là CCustData.

3. Dùng cửa sổ Properties để đổi thuộc DataSourceBehavior thành 1- vbDataSource.

4. Dùng menu Project, References để thiết lập một tham chiếu đến MicrosoftActiveX Data Objects.

5. Trong phần khai báo của lớp, tạo một đối tượng Recordset (private). Đối tượng này sẽ xử lý truy cập cơ sở dữ liệu.

Private mrsCustomer As ADODB.Recordset

6. Trong sự kiện Initialize của lớp, viết chương trình để tạo đối tượng Recordset:

Set mrsCustomer = New ADODB.Recordset
    mrsCustomer.Source = "select * from tblCustomer" mrsCustomer.CursorType = adOpenKeyset mrsCustomer.LockType = adLockOptimistic mrsCustomer.ActiveConnection = "DSN=JetNovelty;" mrsCustomer.Open
    

7. Trong sự kiện Initialize của lớp, viết chương trình đăng ký nguồn dữ liệu với tập hợp DataMembers do thư viện Microsoft Data Binding cung cấp. Điều này cho phép phần tiêu thụ dữ liệu (như là các điều khiển ràng buộc) dùng lớp này như là một nguồn dữ liệu :

8. Viết chương trình cho sự kiện GetDataMember của lớp để trả về một đối tượng Recordset dựa trên tham số DataMember của sự kiện ( Sự kiện GetDataMember sẽ hiện diện sau khi ta quy định giá trị cho thuộc tính DataSourceBehavior). Bởi vì sự kiện GetDataMemberđược tham số hoá, ta có thể kết nối ứng dụng với vô số các recordset; tuy nhiên, lớp này chỉ trả về một danh sách khách hàng.

Tham số Data của sự kiện GetDataMember là một đối tượng, không phải một recordset. Do đó, trong sự kiện có thể truy cập đối tượng khác thay vì đối tượng Recordset của ADO.

9. Kế đến, viết phương thức (public) trong lớp CCustData để điều khiển recordset. Trong ví dụ này, ta tạo 4 phương thức di chuyển được cung cấp bởi một điều khiển dữ liệu:

Public Sub MoveFirst() mrsCustomer.MoveFirst End Sub
    Public Sub MoveLast() mrsCustomer.MoveLast End Sub
    Public Sub MoveNext()
    mrsCustomer.MoveNext
    If mrsCustomer.EOF Then mrsCustomer.MoveLast End If
    End Sub
    Public Sub MovePrevious() mrsCustomer.MovePrevious If mrsCustomer.BOF Then mrsCustomer.MoveFirst End If
    End Sub
    

10. Dùng menu Project Components, thêm một điều khiển Microsoft DataGrid Control6.0(OLEDB) vào đề án.Nó cho phép ta hiển thị dữ liệu trong một lưới (grid). Tạo một instance của điều khiển lưới trên biểu mẫu.

11. Trên biểu mẫu, tạo 4 nút lệnh để duyệt qua dữ liệu. Đặt tên chúng là cmdFirst, cmdPrevious, cmdNext,cmdLast.

12. Trong sự kiện Load của biểu mẫu, khai báo một instance của lớp nguồn dữ liệu. Viết chương trình cho sự kiện Click để gọi các phương thức di chuyển :

Private Sub Form_Load()
    ' Create the data source object
    Set mCustData = New CCustData
    ' Bind the object to grid
    Set DataGrid1.DataSource = mCustData
    DataGrid1.DataMember = "Customers" End Sub
    Private Sub cmdFirst_Click()
    mCustData.MoveFirst
    End Sub
    Private Sub cmdLast_Click()
    mCustData.MoveLast
    End Sub
    Private Sub cmdNext_Click()
    mCustData.MoveNext
    End Sub
    Private Sub cmdPrevious_Click()
    mCustData.MovePrevious
    End Sub
    

13. Thi hành ứng dụng.

Tạo lớp xuất dữ liệu

Có nhiều khả năng ta viết một thủ tục lấy một bảng cơ sở dữ liệu và chuyển đổi nó thành tập tin văn bản có phân cách, sau đó ta sẽ sử dụng lại thủ tục này nhiều lần.

Phần này xây dựng trên hàm xuất HTML mô tả trong chương 14 “Thiết lập báo cáo và xuất thông tin ” để cung cấp việc xuất dữ liệu ta đã sử dụng lớp CCustomer

Để cung cấp cho lớp CCustomer khả năng xuất, ta thêm một thuộc tính và một phương thức cho lớp. Thuộc tính mới, HTMLText, lấy thuộc tính của đối tượng CCustomer và định dạng nó thành một trang HTML. Thủ tục thuộc tính này gọi một hàm (private), HTMLRow để định dạng từng dòng của bảng.

Public Property Get HTMLText() As String
    Dim str As String
    str = "<html>" & vbCrLf
    str = str & "<head>" & vbCrLf
    str = str & "<title>" & "Customer: " & _ FirstName & " " & _
    LastName & _ "</title>" & vbCrLf
    str = str & "<body bgcolor=#ffffff>" & vbCrLf
    str = str & "<font face=Arial,Helvetica>" & vbCrLf str = str & "<table border>" & vbCrLf
    str = str & HTMLTableRow("First name:", FirstName) str = str & HTMLTableRow("Last name:", LastName) str = str & HTMLTableRow("Address:", Address)
    str = str & HTMLTableRow("City:", City)
    str = str & HTMLTableRow("State:", State)
    str = str & "</table>"
    str = str & "</font>" & vbCrLf str = str & "</body>" & vbCrLf str = str & "</html>" & vbCrLf HTMLText = str
    End Property
    

Đoạn chương trình trên chỉ định dạng HTML mà thôi. Quá trình xuất gồm 2 phần: thứ nhất, định dạng dữ liệu trong HTML, thứ hai, ghi nó ra tập tin. Như vậy, ta phải viết thủ tục riêng để thi hành từng tác vụ.

Phương thức SaveHTML của đối tượng Customer lưu dữ liệu HTML được định dạng thành một tập tin.

Public Sub SaveHTML(strFileName As String) Dim fs As Scripting.FileSystemObject
    Dim txt As Scripting.TextStream
    Set fs = New Scripting.FileSystemObject
    Set txt = fs.OpenTextFile(strFileName, ForWriting, True)
    txt.Write HTMLText txt.Close
    Set txt = Nothing
    Set fs = Nothing
    End Sub
    

Đưa các thủ tục này thành một phần của lớp CCustomer, tạo một ứng dụng cho phép người sử dụng cung cấp ID của khách hàng và tên tập tin xuất. Khi người sử dụng nhấn một nút lệnh, khách hàng được chọn sẽ được xuất vào tập tin HTML chỉ ra bởi người sử dụng.

Option Explicit
    Private Cust As CCustomer
    Private Sub Form_Load()
    Set Cust = New CCustomer
    End Sub
    Private Sub cmdExport_Click() Cust.GetData txtID.Text
    Cust.SaveHTML App.Path & "" & txtFilename.Text
    MsgBox "File saved.", vbInformation
    End Sub
    

Tập tin HTML được tạo bởi phương thức xuất :

lM r

Triển khai lớp thành Active Server

Ta có thể dùng Visual Basic để biên dịch các đề án dựa trên lớp thành các thành phần ActiveX. Các thành phần này, dưới dạng các DLL hay EXE, cung cấp các chức năng của đối tượng mà không cần phân phát hay sao chép mã nguồn của lớp. Nó tiện dụng khi ta dùng lại chương trình trong nhiều đề án cũng như với nhiều lập trình viên.

Tạo thành phần ActiveX từ lớp cũng cho ta khả năng phân phát đối tượng từ xa, như trong chương 15.

Để tạo đề án của thành phần ActiveX trong Visual Basic, ta bắt đầu tạo một đề án mới. Khi Visual Basic yêu cầu ta cung cấp kiểu đề sẵn, chọn ActiveX DLL hay ActiveX EXE. Một đề án mới được tạo với một mô-dun lớp duy nhất. Sau đó, ta có thể thêm các lớp khác để lập trình. Bước cuối cùng là biên dịch toàn bộ thành ActiveX DLL hay ActiveX EXE.

Biên dịch đề án ActiveX tương tự biên dịch với đề án thông thường. Điểm khác biệt là việc sử dụng ActiveX DLL và ActiveX EXE được thiết kế để dùng với các ứng dụng khác.

Sử dụng thành phần ActiveX trong một đề án thông thường STANDARD EXE

Sau khi biên dịch thành phần ActiveX, ta có thể lập một tham chiếu đến nó từ trong các đề án khác của Visual Basic. Khi ta thực hiện điều này, nghĩa là ta có thể dùng lớp chứa trong thành phần ActiveX để tạo đối tượng trong đề án. Điều này cho phép ta tận dụng tính năng của thành phần ActiveX một cách đơn giản, nhất quán, không bận tâm đến chương trình bên trong của thành phần.

Để thực hiện tham chiếu ActiveX Server dùng menu ProjectReferences.

Biên dịch ActiveX Server

1. Tạo một đề án Visual Basic mới. Khi Visual Basic yêu cầu ta cung cấp kiểu đề

án cần tạo, chọn ActiveX DLL.

2. Trong cửa sổ Properties, sửa thuộc tính Name của đề án ActiveX DLL thành CustSr v .

3. Visual Basic thêm một lớp rỗng, gọi là Class1, vào đề án ActiveX DLL một cách mặc định. Nhấn nút phải chuột lên lớp, chọn Remove Class1 từ menu bật ra để loại bỏ lớp này.

4. Bởi vì ta sắp thêm vào đề án một lớp sử dụng ADO,ta dùng menu Project Refenrences để lập một tham chiếu đến MicrosoftActiveXDataObjects2.0. Nếu muốn dùng phiên bản của CCustomer xây dựng trong phần xuất ra HTML trước đây, lập một tham chiếu đến Microsoft Scripting Library.

5. Kế đến, thêm lớp được tạo trước đó vào đề án ActiveX DLL. Để thực hiện điều này, nhấn nút phải chuột lên đề án CustSrv, chọn Add từ menu bật ra. Chọn Class Module.

6. Hộp thoại Add Class Module xuất hiện. Chọn tab Existing. Chọn lớp CCustomer .

7. Trong thuộc tính của lớp CCustomer, đổi thuộc tính Instancing thành 5_Multiuse.

8. Nếu cần, thêm trình thiết kế DataEnviromentta tạo trước đó vào đề án. Thực hiện bằng cách chọn menu Project,AddFile,rồi chọn tập tin deNovelty.Dsrtừ hộp thoại tập tin.

9. Biên dịch đề án bằng cách chọn menu File, Make CustSrv.dll.

10. Hộp thoại MakeProject xuất hiện. Chọn thư mục lưu DLL và nhấn OK.

ActiveX DLL được biên dịch là CustSrv.dll ta có thể sử dụng nó trong bất kỳ đề án nào.

Sử dụng ActiveX Server

1. Tạo một đề án mới kiểu Standard EXE.

2. Tìm và lập tham chiếu đến CustSrv trong menu Project References.

3. Trong biểu mẫu, đưa vào đoạn chương trình tạo instance của đối tượng từ ActiveX server và trả về thông tin từ cơ sở dữ liệu dưới dạng một đối tượng.

Option Explicit
    ' References CustSvr
    Private Cust As CCustomer
    Private Sub Form_Load()
    Set Cust = New CCustomer
    End Sub
    Private Sub cmdGetCust_Click() Cust.GetData txtID.Text
    MsgBox Cust.FirstName & " " & _ Cust.LastName & " " & _ Cust.Address & " " & _ Cust.City & " " & _
    Cust.State
    End Sub
    

4. Thi hành ứng dụng. Nó sẽ hiển thị dữ liệu từ cơ sở dữ liệu khi ta nhập một số hợp lệ trong hộp văn bản và nhấn nút lệnh.

Đối với một ứng dụng độc lập thì ứng dụng này có lợi ích không rõ rệt nếu ta dùng trong ứng dụng phân tán thì nó có lợi ích đáng kể.

Để có thể triển khai từ xa qua mạng có thể dùng MicrosoftTransaction Server.

Đăng ký thành phần trong ActivateX trên máy người sử dụng

Thành phần ActiveX cần được đăng ký trên máy tính để sử dụng lại trên máy đó. Việc đăng ký bảo đảm rằng hệ điều hành sẽ nhận ra sự tồn tại của thành phần mỗi khi ứng dụng tạo đối tượng từ đó.

Khi ta làm việc với ActiveX server trên một máy tính dùng vào việc phát triển phần mềm, việc đăng ký không là vấn đề. Bởi vì thành phần được tự động đăng ký với Visual Basic ngay lúc chúng được biên dịch. Tuy nhiên khi ta phân phát thành phần đến người sử dụng, ta phải bảo đảm rằng thành phần ActiveX được đăng ký trên máy người sử dụng. Có một số phương pháp để thực hiện điều này.

Sử dụng Trình đóng gói và triển khai ứng dụng (Package and Deployment Wizard) để phân phát người sử dụng.

Sử dụng bằng phương pháp thủ công dùng tiện ích Regsrv32. EXE.

Chuyển đổi đề án Standard EXE thành đề án ActivateX

Ta có thể chuyển đổi đề án StandardEXE thành đề án ActiveX khi ta dự định dùng lại một đề án có sẵn và biến nó thành thành phần ActiveX độc lập.

Ngoài ra, ta có thể chuyển đổi giữa 2 kiểu thành phần ActiveX : ActiveXDLLActiveX EXE) bằng cách đổi thuộc tính của đề án :

1. Trong Visual Basic, mở đề án ta dự định chuyển đổi.

2. Chọn menu ProjectProperties.

3. Chọn kiểu đề án :

Sử dụng thành phần ActiveX từ xa

Khả năng biên dịch bộ các lớp độc lập thành các thành phần ActiveX là phần quan trọng của truy cập cơ sở dữ liệu từ xa. Trong môi trường Client/Server,ta có thể dùng ActiveX Server để xử lý tương tác giữa ứng dụng Client và các Servercơ sở dữ liệu.

Tạo thành phần đa luồng

Visual Basic có khả năng tạo thành phần ActiveX đaluồng(multi-thread).Với đa luồng, thành phần thi hành theo cách đáp ứng hơn. Bởi vì hệ điều hành có thể cấp phát tài nguyên bộ xử lý cho nhiều luồng; nếu thành phần thi hành với nhiều luồng, chức năng của thành phần được chia thành nhiều khối cho nhiều luồng (một số luồng có thể được gán những mức ưu tiên cao bởi hệ điều hành ). Ta có thể xem luồng như đơn vị điều khiển nhỏ nhất của hệ điều hành có khả năng lập lịch biểu thi hành.

Ngoài ra, trên những máy có nhiều bộ vi xử lý, hệ điều hành có khả năng gán những luồng nhất định để thi hành trên những bộ vi xử lý riêng. Cho thành phần khả năng đa luồng là giải pháp tận dụng tối đa năng lực máy tính với nhiều bộ vi xử lý.

Thêm hỗ trợ đa luồng trong thành phần chỉ đòi hỏi ta đổi thuộc tính đề án vào lúc biên dịch. Không có thay đổi nào khác trong chương trình.

1. Trong Visual Basic, mở đề án của thành phần (ActiveX EXE,ActiveX DLL, điềukhiểnActiveX).

2. Từ menu Project,chọn Properties

3. Chọn Apartment Threaded trong bảng Threading Model.

4. Nhấn OK. Khi đề án được biên dịch, nó sẽ có hỗ trợ đa luồng.

Ta có thêm khả năng bổ sung cho ActiveX EXE là : Thread perObject hay ThreadPool.ThreadperObjectcó nghĩa là ActiveXEXEsẽ sinh ra một luồng cho mỗi đối tượng được tạo. Điều này cung cấp khả năng hoạt động tốt nhất, nhưng có thể tiêu tốn nhiều tài nguyên máy tính.

ThreadPool, trái lại, cho phép ta kiểm soát có bao nhiêu luồng mà thành phần ActiveX có thể tạo cùng một lúc, cho phép ta hạn chế tài nguyên tiêu tốn bởi thành phần. Tuy nhiên, nếu số đối tượng yêu cầu vượt quá số luồng trong Threadpool của Server của thành phần, những yêu cầu đến sau trên đối tượng của Server sẽ bị ngăn lại cho đến khi quá trình của Client giải phóng một luồng.

Các hạn chế của thành phần đa luồng

  • Ngôn ngữ hạn chế hỗ trợ đa luồng: Đây là chuyển đổi biên dịch. Ta không thể viết chương trình để làm gì với nó cả.
  • Không có trình gỡ rối hỗ trợ đa luồng.
  • Không có hỗ trợ đa luồng trong ứng dụng MDI
  • Không hỗ trợ cho các điều khiển ActiveX đơn luồng trong ứng dụng đa luồng: Điểm hạn chế này bị áp đặt bởi Visual Basic do vấn đề lớn khả năng hoạt động sinh ra bởi tổ hợp của một điều khiển đơn luồng trong một nơi chứa đa luồng. Điều này có nghĩa là nếu ta tạo một điểu khiển ActiveX đa luồng sử dụng các điều khiển đơn luồng khác – nó sẽ không hoạt động. Tuy nhiên phần lớn các điều khiển trong Visual Basic là đa luồng.
  • Các thuộc tính và phương thức được khai báo là Friend không thể gọi qua luồng. Để goi thuộc tính và phương thức đặc biệt gọi qua Public.

Lớp và đối tượng thể hiện lĩnh vực mới của lập trình Visual Basic.

Chương này cung cấp những thông tin để biến các kỹ thuật hướng đối tượng mở rộng thành những hành động, không chỉ là tận dụng những kỹ thuật cao cấp như đa luồng và thành phần, mà còn tạo sự đơn giản và ổn định theo thời gian.

Hỏi:Lớp và đối tượng có vẻ phải xử lý phức tạp. Một điều tôi thắc mắc là “Bạn có thể tạo những ứng dụng đơn giản hơn bằng cách viết thêm chương trình và thêm mô-dun nhiều hơn”. Tôi có nghĩ sai không ?

Đáp:Bạn có phần đúng là khi xây dựng một ứng dụng với lớp và đối tượng thì sẽ tốn nhiều thời gian cho thiết kế và xây dựng lần đầu. Lưu ý rằng một trong những mục tiêu của lập trình hướng đối tượng là tính năng sử dụng lại. Nó sẽ tiết kiệm cho bạn rất nhiều thời gian và sức lực sau này.

Hơn nữa, nó còn giúp bạn dễ bảo trì, dễ gỡ rối.

0