Ch
ng M i B n - Dùng Control Data
ươ
ườ ố
Control Data
ậ ơ ỡ ữ ệ ể t, có m t c s d li u Microsoft gói kèm khi ta mua ừ ậ ỉ ơ ơ Data. Nh ta bi ộ ơ ỡ ữ ệ ư ế ủ T VB5, Visual Basic cho l p trình viên m t control đ truy c p c s d li u, tên nó ộ ch đ n s là VB6 - đó là Jet Database Engine. Jet Database Engine là cái "phòng máy" c a chính MS Access Database Management System.
•
Cho đ n th i VB5, Microsoft cho ta ba k thu t chính: ế ậ ờ ỹ
•
•
ậ ớ ề ủ ệ ư i ích th c ti n. ấ ầ ạ ệ ị dùng v i Jet Database Engine. Nó r t d dùng, hi u năng và ti n, nh ng b gi ấ ễ h n trong ph m vi MS Access. D u v y, nó r t th nh hành vì có l ậ ạ ợ ODBC (Open Database Connectivity): ODBC đ c thi ượ t k đ cho phép ề ỉ ố ớ ủ ạ ậ ế ế ể ấ ậ ậ ộ ọ ặ ộ ỹ ấ ể ầ ấ ừ ư ả ổ ệ ớ ấ ứ ạ ạ ự ử ổ ề ể ấ ố ớ DAO (Data Acess Objects): DAO là k thu t bí truy n c a Microsoft, ch đ ỉ ể ỹ ị ớ i ự ể ầ ấ users n i v i đ lo i databases mà ch dùng m t method duy nh t. Đi u n y c t ấ b t gánh n ng cho l p trình viên, đ ch c n h c m t k thu t l p trình duy nh t ể ỉ ầ ớ ế ầ mà có th làm vi c v i b t c lo i database nào. Nh t là khi sau n y n u c n Access lên SQLServer ch ng h n, ph i thay đ i lo i database, nh nâng c p t ạ ẳ thì s s a đ i v coding r t ít. Khi dùng ODBC chung v i DAO, ta có th cho ớ ắ i c a ODBC là nó r c Access Database n i v i các databases khác. Có m t b t l ộ ấ ợ ủ r i. ố ộ ữ i quy t khó khăn v s r c r i c a ODBC. Cách l p trình v i RDO ề ự ắ ố ủ ể ậ ế RDO (Remote Data Object): M t trong nh ng lý do chính đ RDO đ t k là gi ả ư ế ế ả ư ậ ượ c thi ớ ố ớ đ n gi n nh DAO, nh ng th t ra nó dùng ODBC nên cho phép users n i v i ơ nhi u databases. Tuy nhiên, RDO không đ c th nh hành l m. ượ ề ắ ị
ậ ậ ế ụ ổ ợ ớ ấ ẽ ọ ề ả ớ ỹ ọ ữ ư ể ế ụ ệ ẫ ầ ấ ơ ế ổ ế ấ ữ ỹ ệ ậ ậ ế ẽ ậ ữ ầ ậ VB6 ti p t c h tr các k thu t nói trên, và cho thêm m t k thu t truy c p ộ ỹ ADO (ActiveX Data Objects). Trong m t bài t database m i, r t quan tr ng, đó là ớ i ộ ta s h c v ADO v i nh ng u đi m c a nó. Tuy nhiên, vì DAO r t đ n gi n và ủ ể hi u năng nên ta v n có th ti p t c dùng nó r t h u hi u trong h u h t các áp d ng. ụ ớ Do đó bài n y và bài k s t p trung vào nh ng k thu t l p trình ph bi n v i DAO.
ả ồ ệ ủ ạ ộ ớ ắ ầ ủ ả ồ ữ Cách dùng gi n ti n c a control Data là đ t nó lên m t Form r i làm vi c v i nh ng ệ ớ ặ DataControl Properties c a nó. B n hãy b t đ u m t d án VB6 m i, cho nó tên ộ ự b ng cách click tên project trong Project Explorer bên ph i r i edit property Name ằ trong Properties Window.
Data1 sẽ i Form, gi ng nh m t StatusBar, hãy ư ộ ủ ố ướ ệ ằ 2 - Align Bottom. DoubleClick lên Icon c a Control Data trong Toolbox. M t Control Data tên ộ hi n ra trên Form. Mu n cho nó n m bên d ố set property Align c a nó trong Properties Window thành ủ
ả ế giao tho i cho Data1. đây ta ch n Ở ừ ạ ộ property DatabaseName, k đó click lên nút browse có ba ch m ấ ọ E:\Program ể ủ ạ Click bên ph i hàng đ ch n m t file Access dabase t ể ọ Files\Microsoft Visual Studio\VB98\BIBLIO.MDB , trong computer c a b n có th nó n m trên disk C hay D. ằ
ng trình n y ta mu n làm vi c v i ươ ầ ố ệ ớ table Titles c a database ủ ủ Trong ch BIBLIO.MDB, đ xem và edit các records. Đ ý tr s ể ứ ị ố 2- UseJet, t c là dùng k thu t DAO, thay vì dùng k thu t ODBC. ậ ỹ ể property DefaultType c a Data1 có ậ ỹ
property Recordsource c a Data1, r i click lên cái tam giác nh ồ ẽ ở ủ ấ ỏ Khi b n click lên ạ bên ph i, m t ComboBox s m ra cho ta th y danh sách các tables trong database. ả B n hãy ch n 0 - Table: ộ ọ Titles. Đ ý ể property RecordsetType c a Data1 có tr s là ị ố ủ ạ
m i mà ta s dùng th ng xuyên khi truy c p d li u trong VB6 là ẽ ừ ớ
ộ ố ộ ườ ể ng h p y có th ta l y v t ệ ả ộ ợ ấ ề ề ấ ả ỉ ố ấ ủ Recordset Cái t ậ ữ ệ ườ ộ Set of records, nó có th ch a m t s records hay (b records). Recordset là m t ể ứ ộ ấ ừ ộ không có record nào c . M t record trong Recordset có th là m t record l y t m t ể t c records trong table hay ch nh ng Table. Trong tr ỉ ữ ấ records th a đúng m t đi u ki n, thí d nh ta ch mu n l y các records c a nh ng ữ ụ ư sách xu t b n tr ộ c năm 1990 (Year Published < 1990). ỏ ấ ả ướ
ộ ể ậ ợ ộ ụ ư ừ ấ ệ ố table Titles, ta mu n có thêm chi ti M t Record trong Recordset cũng có th là t p h p các c t (columns) t hai (hay ba) tables qua các m i liên h one-to-one và one-to-many. Thí d nh khi l y các records t ừ ạ t tên công ty (Company Name) và đi n tho i ế ệ ố
ủ ấ ả ằ Foreign Key PubID ế t y. N u ế ấ ể ấ i bài Database. (Telephone) c a nhà xu t b n (table Publishers) b ng cách dùng trong table Titles làm Primary Key trong table Publishers đ l y các chi ti b n ch a n m v ng ý ni m Foreign Key thì hãy đ c l ạ ư ắ ọ ạ ữ ệ
là t p h p c a hai ườ ng h p y ta có th xem nh có m t ể ợ ấ ộ virtual ( o) table ả ư ợ ủ ậ Trong tr tables Titles và Publishers.
Title, Year Published, ISBN và ờ ạ ặ ớ txtTitle, b n hãy đ t lên Form 4 labels v i captions: ươ ứ ế ng ng và đ t tên chúng là ặ Bây gi Publisher ID. K đó cho thêm 4 textboxes t txtYearPublished, txtISBN và txtPublisherID.
ọ ồ ủ ủ t kê tên các Fields trong table Titles. Đó là vì Data1 đ c coi nh trung ư ở ượ database. property Datasource c a nó trong Properties Window Ch n textbox txtTitle, r i set ạ thành Data1. Khi click lên property Datafield c a txtTitle và m ComboBox ra b n s th y li ệ ẽ ấ gian l y table Titles t ấ đây ta s ch n c t Title. ẽ ọ ộ Ở ừ
ọ ộ ư ệ ố ế ầ ị ố ố ị i công tác n y cho 3 textboxes kia, và ch n các c t Year Published (năm xu t L p l ấ ậ ạ ấ ả b n), ISBN (s lý l ch trong th vi n qu c t ), và PubID (s lý l ch nhà xu t b n) ả làm Datafield cho chúng.
ớ ể ạ ế ộ ượ ồ c r i. ng trình đ i đây: t m t hàng code, ta có th ch y ch T i đây, m c d u ch a vi ươ ư ặ ầ t c a record đ u tiên trong table Titles nh d Nó s hi n th chi ti ư ướ ế ủ ị ẽ ể ầ
ạ
ể Navigator Buttons đ đi đ n các record
ế ể ỗ ầ ạ
ể t c a record y s hi n th . N u không dùng các
ộ
và cu i (last) ố ấ ẽ ể
ế ế ủ
ng đ ong b ng cách
ươ
ư
ể
ể
ằ
methods MoveFirst, MovePrevious, MoveNext và
đ uầ B n có th b m các nút di chuy n ể ấ . M i l n b n di chuy n đ n ế c (previous), k (next) (first), tr ướ m t record m i là chi ti ị ế ớ Navigator Buttons, ta cũng có th code đ làm công tác t g i các Recordset ọ MoveLast.
ố ủ
ọ
ự ư ậ nh v y,
ươ
ứ ấ ủ
ể
ọ
ị ế ở ị ế ủ ả
ứ
ế
ả
ộ
ộ
Khi record cu i c a Recordset đang hi n th , n u ta g i method MoveLast thì ể property EOF (End-Of-File) c a Recordset tr thành True. T ng t ủ khi record th nh t c a Recordset đang hi n th , n u ta g i method MovePrevious thì property BOF (Begin-Of-File) c a Recordset tr thành True. ở N u m t Recordset không có ch a m t record nào c thì c hai properties EOF và BOF đ u là True. ề
ặ
ể
ị ữ ệ
ệ ộ
data binding hay data bound (bu c vào d li u) ữ ệ t bà con
Data Aware (bi
c nói là
c g i là ỗ ợ ứ
ầ ượ
ế
Đ c tính hi n th d li u trong các textboxex theo đúng record hi n th i ờ (current record) đ ượ ọ và control TextBox h tr ch c năng n y đ d li u). ữ ệ
ể
ể ổ ừ
ầ ồ
ể ể
ị
ị ạ
ứ i record đ u tiên thì b n s th y là ầ c thay đ i (updated) ổ ậ ự ượ
ể ể ầ
1985 Year Published đ đ i t Khi record đ u tiên đang hi n th , n u b n edit ị ế ạ thành 1983 r i click Navigator button Next đ hi n th record th nhì, k đó ế click Navigator button Previous đ hi n th l ạ ẽ ấ field Year Published c a record đ u tiên đã th t s đ ủ thành 1983.
record n y đ n record khác thì
ằ
ề ầ
ừ
ầ
ầ ế ữ ự
ư
ổ
ế ạ
ổ ạ
ầ property Locked c a các
ư ộ
ủ
ạ
ề ể ể
ư
ể
ể ờ ấ i đây:
Đi u n y có nghĩa r ng khi Data1 navigates t ướ c n u record n y đã có s thay đ i vì user edited, nó l u tr s thay đ i đó tr ự ế khi di chuy n. Ch a ch c là b n mu n đi u n y, do đó, n u b n không mu n ố ố ắ user tình c edit m t record thì b n có th set textboxes y thành True đ user không th edit các textboxes nh trong hình d ướ
Ch đ nh v trí Database lúc ch y ch
ng trình
ạ
ỉ
ị
ị
ươ
t k (at design time) ta đã dùng ỉ ế ế ạ ị c đây tuy ti n l ng trình n y lên Cách ch đ nh tên DatabaseName trong giai đo n thi tr ư i nh ng h i nguy hi m, vì khi ta cài ch ể ệ ợ ướ ơ ươ ầ
Dim AppFolder As String Private Sub Form_Load() ' Fetch Folder where this program EXE resides AppFolder = App.Path ' make sure it ends with a back slash If Right(AppFolder, 1) <> "\" Then AppFolder = AppFolder & "\" ' Assign Full path database filename to Data1 Data1.DatabaseName = AppFolder & "BIBLIO.MDB" End Sub
ắ ư ủ ấ ằ ộ ụ ủ ươ ủ ể ố ớ property Path c a Application Object computer c a khách, ch a ch c file database y n m trong m t folder có cùng tên. Thí d trên computer mình thì database n m trong folder E:\Program Files\Microsoft ằ Visual Studio\VB98, nh ng trên computer c a khách thì database n m trong folder ư ằ ng trình kh i đ ng ta nên xác đ nh C:\VB6\DataControl ch ng h n. Do đó, khi ch ạ ị ở ộ ẳ d ta mu n đ database trong cùng m t folder v i ch i v trí c a database. Gi l ươ ng ộ ả ụ ạ ị App nh sau: trình đang ch y, ta có th dùng ư ể ạ ủ
ớ ươ ấ ẽ ả i ta cài ch ả ng trình b n t ng đâu trong hard disk c a computer ươ ế ầ ỗ ng trình tìm th y file database đúng ch , ạ ở ủ V i cách code nói trên ta s đ m b o ch không c n bi ườ khách.
ế ừ ạ xa, khi n p bài database cho giám th VB6 mà b n ị ị ị t k thì giám th (tutor) ế ế ủ ộ t ch t c ng) v trí c a file database trong lúc thi ị ẽ ứ ư ọ ế ứ ự ầ N u b n đang h c VB6 t ạ hardcode (vi ế cũng g p cùng s khó khăn n y vì ch a ch c giám th s ch a database trong m t ộ ắ ặ folder có cùng tên nh trong harddisk c a b n. ủ ạ ư
Thêm b t các Records
ớ
ng trình trên dùng cũng t m đ ươ ựợ ư ạ ươ ng ti n đ thêm ể cmdEdit, ớ c, nh ng nó không cho ta ph ệ b n hãy đ vào Form 5 buttons tên: ờ ạ Ch (add), b t (delete) các records. Bây gi ể cmdNew, cmdDelete, cmdUpdate và cmdCancel.
ấ ạ ư ặ ầ ậ Data1 có m t ộ property ể ừ ế ấ ằ record n y đ n record ế ế t) database ta dùng ấ ừ ỗ ầ ớ M c d u b n không th y, nh ng th t ra Control Data Recordset và khi ta dùng Navigator buttons là di chuy n t ầ khác trong Recordset y. Ta có th nói đ n nó b ng Notation (cách vi ể Data1.Recordset, và m i l n mu n l y Recordset m i nh t t ố ấ method Refresh nh ư Data1.Recordset.Refresh.
ơ ớ ở ộ ầ ẽ Lúc chu ng trình m i kh i đ ng, user đang xem (browsing) các records thì hai buttons Update và Cancel không c n ph i làm vi c. Do đó ta s nhân ti n Lock (khóa) các ệ textboxes và disable (làm cho b t l c) hai buttons n y vì không c n dùng chúng. ả ấ ự ệ ầ ầ
Sub SetControls(ByVal Editing As Boolean) ' Lock/Unlock textboxes txtTitle.Locked = Not Editing txtYearPublished.Locked = Not Editing txtISBN.Locked = Not Editing txtPublisherID.Locked = Not Editing ' Enable/Disable buttons CmdUpdate.Enabled = Editing
i đây, ta dùng m t parameter g i là ộ ướ ớ ị ố Editing v i tr s Browse mode và Edit ọ ượ Trong Sub SetControls d ọ False hay True tùy theo user đang Browse hay Edit, ta g i là mode. Trong Edit mode, các Textboxes đ ở cmdNew, cmdDelete và cmdEdit tr nên b t l c: c unlocked (m khóa) và các nút ấ ự ở
CmdCancel.Enabled = Editing CmdDelete.Enabled = Not Editing cmdNew.Enabled = Not Editing CmdEdit.Enabled = Not Editing End Sub
Trong Browse mode, Form có d ng nh sau: ư ạ
Private Sub Form_Load() ' Fetch Folder where this program EXE resides AppFolder = App.Path ' make sure it ends with a back slash If Right(AppFolder, 1) <> "\" Then AppFolder = AppFolder & "\" ' Assign Full path database filename to Data1 Data1.DatabaseName = AppFolder & "BIBLIO.MDB" ' Place controls in Browse Mode SetControls (False) End Sub
Private Sub CmdEdit_Click() ' Place controls in Edit Mode SetControls (True) End Sub
Sub Form_Load khi ch ng trình kh i đ ng và ượ ọ ươ ở ộ c g i trong Sub SetControls đ trong Sub CmdEdit khi user click nút Edit nh sau: ư
Private Sub CmdDelete_Click() On Error GoTo DeleteErr With Data1.Recordset ' Delete new record .Delete ' Move to next record
ộ ủ ị ổ i (current record) ệ ạ ổ ổ ả MoveNext. Kh n i, ộ ừ property EOF c aủ ả i ph i ể ề ế ạ ậ ủ Sub ẽ ể ể ư Khi ta Delete m t record trong recordset, v trí c a record hi n t v n không thay đ i. Do đó, sau khi delete m t record ta ph i ẫ n u ta v a delete record cu i c a Recordset thì sau khi MoveNext, ố ủ ế Recordset s thành True. Thành ra ta ph i ki m tra đi u đó, n u đúng v y thì l ả MoveLast đ hi n th record cu i c a Recordset nh trong code c a ố ủ cmdDelete_Click d i đây: ị ướ
.MoveNext If .EOF Then .MoveLast Exit Sub End With DeleteErr: MsgBox Err.Description Exit Sub End Sub
Private Sub cmdNew_Click() ' Place Recordset into Recordset AddNew mode Data1.Recordset.AddNew ' Place controls in Edit Mode SetControls (True) End Sub
ậ ằ ộ ỉ ậ ể ọ ủ ộ ư trong ở ặ ụ ư Data1.Recordset.Edit. T ươ ư ậ ộ Trong lúc code, ta Update (c p nh t hóa) m t record trong Recordset b ng method Update. Nh ng ta ch có th g i method Update c a m t Recordset khi Recordset ằ Edit hay AddNew mode. Ta đ t m t Recordset vào Edit mode b ng đang ộ cách g i ọ method Edit c a Recordset, thí d nh ự ng t ủ nh v y, ta đ t m t Recordset vào AddNew mode b ng cách g i ọ method AddNew ặ c a Recordset, thí d nh ủ ằ ụ ư Data1.Recordset.AddNew.
ọ
ấ
ỏ
thoát ra kh i AddNew hay Edit modes, hay nói cho
ể ự
ỏ
ọ method
ờ ợ
ơ
Sau khi Recordset g i method Update thì Recordset y ra kh i AddNew hay Edit modes. Ta cũng có th t đúng h n là h y b m i pending (đang ch đ i) Update b ng cách g i ủ ỏ ọ CancelUpdate, thí d nh
ằ ụ ư Data1.Recordset.CancelUpdate.
Dùng DataBound Combo
ươ ỉ ể ị ng trình hi n t ệ ạ ế ị ặ ầ ươ ả c ớ ể ấ ả ng trình l u tr ư ệ ể ả ỏ ớ i ta ch hi n th lý l ch nhà xu t b n (PubID) c a Title, ủ t. Ph i chi m c d u ch ữ PubID, nh ngư ị ượ Company Name c a nhà xu t b n cho ta làm vi c đ kh i ph i nh ấ ả ề ủ ể ự ệ ằ Project | Trong ch ch không có thêm chi ti hi n th đ các con s thì hay quá. Ta có th th c hi n đi u đó b ng cách dùng Control ố DBCombo (Data Bound Combo). B n hãy dùng IDE Menu Command ạ Components... đ ch n Apply. ể ọ Microsoft Data Bound List Controls 6.0 r i click ồ
ầ ộ ấ DBCombo1 vào Form. Vì ta c n m t Recordset khác ứ ạ ộ
i ta th y hình Data2 lúc run-time, ườ ể ấ property Visible nó thành False. K đó, thêm m t DBCombo tên ộ ế đ cung c p Table Publisher cho DBCombo1, nên b n hãy thêm m t control Data th ể nhì tên Data2 vào Form. Cho Data2, hãy set property DatabaseName thành E:\Program Files\Microsoft Visual Studio\VB98\BIBLIO.MDB và property RecordSource thành Publishers. Đ không cho ng b n hãy set ạ
ủ ư ụ ấ ả ể ị ổ ứ ằ ẫ
ươ ứ ấ ả ứ Cái m c đích c a chúng ta khi dùng DBCombo1 là hi n th Company Name c a nhà ủ ệ ớ xu t b n, nh ng đ ng sau l ng thì không có gì thay đ i, t c là ta v n làm vi c v i ư PubID cho các record Title c a Data1. Khi user click lên DBCombo1 đ ch n m t nhà ộ ể ọ ủ xu t b n, thì ta theo Company Name đó mà ch a PubID t ng ng trong record Title c a Data1. Do đó có nhi u th ta ph i s p đ t cho DBCombo1 nh sau: ủ ả ắ ư ứ ề ặ
Property
Value
Chú thích
Nó cung c p table
ấ
RowSource
Data2
Đây là datasource c a chính DBCombo1. ủ Publishers.
ọ ồ
ủ c ch n r i, Combo c a ượ ị
ủ
Listfield
Company Name
ủ
Khi RowSource phía trên đã đ property Listfield n y s hi n th các fields c a table ầ ẽ ể Publishers. Company Name là field c a RowSource mà ta mu n hi n th trên DBCombo1.
ể
ố
ị
ủ
ứ
ố
DataSource
Data1
Đây là datasource c a record mà ta mu n. edit, t c là record c a table Titles ủ
Datafield
PubID
Field (c a record Title) s đ
c thay đ i.
ẽ ượ
ủ
ổ
ươ ứ
ớ ng ng v i
BoundColumn
PubID
Field trong RowSource (table Publishers) t item user ch n trong DBCombo1 (Company Name).
ọ
Private Sub DBCombo1_Click(Area As Integer) ' Display new PuBID txtPublisherID.Text = DBCombo1.BoundText End Sub
ọ ồ ộ ể ổ ị c khi Update b n mu n th y PubID m i hi n th trong ấ ướ ể ế ớ ố ị Khi trong Edit mode user ch n m t Company Name khác trong DBCombo1 r i click ố nút Update b n s th y Textbox txtPublisherID cũng đ i theo và hi n th con s lý ạ ẽ ấ l ch PubID m i. N u tr ạ ớ ị Textbox txtPublisherID thì b n có th dùng Event Click c a DBCombo1 nh sau: ư ủ ể ạ
Private Sub cmdNew_Click() ' Place Recordset into Recordset AddNew mode Data1.Recordset.AddNew ' Default Publisher is "GLOBAL ENGINEERING", i.e. PubID=324 DBCombo1.BoundText = 324 ' Place controls in Edit Mode SetControls (True) End Sub
ể t hay đ c) đ ọ ế ị ố ủ ố ụ ư ạ ượ ộ ỗ ứ ủ ể Property BoundText c a DBCombo1 là tr s c a BoundColumn mà ta có th truy ủ c. Thí d nh b n mu n m i khi thêm m t record Title m i c p (vi ớ ậ ạ thì default PubID là 324, t c là Company Name= "GLOBAL ENGINEERING". B n có th assign tr s 324 vào property BoundText c a DBCombo1 trong Sub cmdNew_Click nh sau: ị ố ư
Trong bài t i ta s h c thêm v cách coding đ dùng Recordset trong k thu t DAO. ớ ẽ ọ ể ề ậ ỹ