Directory listing of http: uap.unnes.ac.id ebook biblebook Visual Basic 6 com & Library Books

16
C H A P T E R

Working with
Recordsets —
Part I I I









In This Cha pter
Updating fields in a
reco rdset

I


n this c hapter, I’ll wrap up my c o verage o f the ADO
Recordset o bjec t by disc ussing ho w to update the info rmatio n in a partic ular rec o rd, and then I’ll explain o ther mo re
advanc ed ideas suc h as batc h updates and transac tio ns. I’ll
c o nc lude the c hapter by c o vering ho w to c lo ne rec o rdsets,
resync , and requery rec o rdsets, and ho w to return multiple
rec o rdsets. I’ll also sho w yo u so me alternate ways to get data,
and finally, ho w to set the c ac he size fo r rec o rdsets.

Up until this po int, I’ve fo c used o n ho w to mo ve the c urrent
rec o rd po inter aro und in a Recordset o bjec t and ho w to
ac c ess individual fields in it. No w it’s time to disc uss ho w to
c hange the info rmatio n in a rec o rdset. Yo u c an insert, delete,
and update the individual rec o rds in a rec o rdset by using the
AddNew, Delete and Update metho ds.

Updating Recordsets
Updating rec o rds in a Recordset c an invo lve no mo re than
selec ting the appro priate LockType when yo u o pen the
rec o rdset. After the user has updated the field using bo und
c o ntro ls o r with c o de in yo ur pro gram that explic itly c hanges

a field’s Value pro perty, using any o f the mo ve metho ds will
auto matic ally save the c hanges. Ho wever, having a deeper
understanding o f ho w the update pro c ess wo rks will help yo u
fine-tune yo ur applic atio n to run faster and better.
Rec o rdset Update Demo The Rec o rdset Update Demo pro gram
(see Figure 16-1) is designed to let yo u try different appro ac hes
to updating a rec o rdset while watc hing the vario us indic ato rs.

Adding and deleting
reco rds in a reco rdset
Batching chang es
Using transactio ns
W o rking with
disco nnected
reco rdsets
W o rking with o ther
reco rdset functio ns










328

Part III ✦ Hard Core ADO

While this pro gram is similar to the Rec o rdset Mo vement Demo pro gram (and uses
muc h o f the same c o de), it is mo re c o mplic ated to use. In the Rec o rdset Mo vement
Demo pro gram, mo st o f the ac tivities require o nly o ne butto n c lic k in o rder to perfo rm a func tio n. The Rec o rdset Update Demo pro gram usually requires a number
o f separate steps in o rder to ac c o mplish a task suc c essfully. This pro c ess merely
reflec ts the number o f individual steps it takes to update a database rec o rd.

Figure 16-1: Running the Recordset Update Dem o program

On the
CD-ROM


You can find the Recordset Update Dem o program on the CD-ROM in the
\VB6DB\Chapter16\RecordsetUpdateDemo directory.

Like the Rec o rdset Mo vement Demo pro gram, the Rec o rdset Update Demo pro gram
relies o n bo und c o ntro ls to display info rmatio n fro m the database. I used a different
table in this pro gram to sho w yo u ho w to use an image to display a pic ture fro m
an Image field in the table. Unfo rtunately, yo u c an o nly display an image fro m the
database with the Image c o ntro l. Yo u must manually lo ad the image file fro m disk
to update the value in the database. See Chapter 15 fo r mo re details abo ut ho w to
use the AppendChunk metho d to lo ad a file to the Image field.

Chapter 16 ✦ Working with Recordsets —Part III

In a typic al update sc enario , yo u press the Add New butto n to c reate a new rec o rd
in the database and then fill in values fo r the two bo und fields (Invento ryId and
Seq). Next, yo u press the Lo ad Image butto n to fill in a value fo r the image field.
Finally, yo u press the Update butto n to save the image to the database. Of c o urse,
this simple example assumes that yo u have o pened the rec o rdset with a c urso r that
c an be updated.

Tip

I did it first: I often find m yself w riting sm all program s that allow m e to explore
the various features of an object. The program usually starts out sim ple and often
ends up fairly com plex. The Recordset Update Dem o and the Recordset
Movem ent Dem o program s provide exam ples of applications that I w rote to test
various features in ADO. Rather than w rite your ow n sm all program s to try com binations of things in ADO, I suggest you use these program s instead. They’ll save
you a lot of tim e and energy.

Updating an existing record
The update pro c ess begins as so o n as yo u mo ve the c urrent rec o rd po inter to a
new ro w. If yo u selec ted pessimistic lo c king when yo u o pened the rec o rdset, the
database server will immediately plac e a lo c k o n the ro w, preventing any o ther user
fro m ac c essing the ro w until yo u have finished wo rking with it.
Note

The read-only and the batch: This section addresses only w hat happens w hen
you use pessim istic or optim istic locking w ith a server-side cursor. Obviously, you
can’t update a recordset that w as opened in read-only m ode, and I’ll cover batch
optim istic locks and client-side cursors later in this chapter under “Perform ing

batch updates” and “Working w ith Disconnected Recordsets,” respectively.

When the ro w is retrieved fro m the datab ase server, its values will b e made
availab le to yo u in the Fields c o llec tio n o f the Recordset o b jec t. As yo u saw in
Chapter 15, eac h Field o b jec t in the c o llec tio n keeps the o riginal value o f the
field as it was retrieved separate fro m the c urrent value as seen b y yo ur pro gram. The c urrent value is sto red in the Value pro perty, while the o riginal value
is sto red in the OriginalValue pro perty. A third value, whic h is availab le o n
demand, allo ws yo u to retrieve the value o f the field as it c urrently exists in the
datab ase server at that instant. The UnderlyingValue pro perty is useful o nly
with o ptimistic lo c king, sinc e it is impo ssib le fo r the value o f the field to c hange
while the ro w is lo c ked using pessimistic lo c king.
Note

Binding effects: Bound controls w ork exactly the sam e w ith Recordset objects
as they do w ith the ADO Data Control. When the user changes a value in a
bound control, the Value property of the Field object w ill be changed autom atically. This action triggers all of the associated processes for the Recordset.

329

330


Part III ✦ Hard Core ADO

Initially, the EditMode pro perty will be set to adEditNone (0), whic h means that no
c hanges have o c c urred to the rec o rd. The mo ment o ne o f the values c hanges, the
EditMode pro perty will be set to adEditInProgress (1), whic h means that o ne o r
mo re values o f the c urrent rec o rd have been c hanged.
Onc e yo u’ve finished c hanging the values in the c urrent ro w, yo u c an dec ide
whether to save yo ur c hanges o r to disc ard them. In database terms, yo u either
perfo rm a co mmit to save yo ur c hanges o r a ro ll back to undo all o f yo ur c hanges.
If yo u c ho o se to ro ll bac k yo ur c hanges, yo u must c all the Cancel metho d (see
Listing 16-1). This metho d takes c are o f undo ing yo ur c hanges in the database.
While it is unlikely, it is po ssible that yo u may get a run-time erro r when using
the Cancel metho d.

Listing 16-1: The Command12_Click event in Recordset
Update Demo
Private Sub Command12_Click()
On Error Resume Next
Images.Cancel

If Err.Number 0 Then
WriteError
End If
Text10.Text = FormatNumber(Images.EditMode, 0)
End Sub

Updating the data is a lo t mo re c o mplex than c anc eling the update, even tho ugh the
c o de is similar (see Listing 16-2). What happens under the c o vers depends o n the
lo c king mo de yo u c ho se. If yo u c ho se pessimistic lo c king, the values will be returned
to the database server and applied to the database. The EditMode pro perty will be
reset to adEditNone. The lo c k o n the rec o rd at the database server will remain in
plac e until yo u mo ve to a new ro w.
If yo u c ho se o ptimistic lo c king, a series o f ac tivities will take plac e. First, a lo c k is
plac ed o n the ro w at the database server. Then, fo r eac h field in the rec o rdset’s
Fields c o llec tio n, the OriginalValue pro perty will be c o mpared to the Underlying
Value pro perty. If there are any differenc es, the Update metho d will be terminated,
an erro r will be returned in the Errors c o llec tio n and the lo c k will be released. If
the o riginal values are the same as the underlying values, the c hanged values in the
Value pro perty will be saved to the database server. Then the lo c k o n the c urrent
ro w will be released, and EditMode will be reset to adEditNone.


Chapter 16 ✦ Working with Recordsets —Part III

Listing 16-2: The Command10_Click event in
Recordset Update Demo
Private Sub Command10_Click()
On Error Resume Next
Images.Update
If Err.Number 0 Then
WriteError
End If
Text10.Text = FormatNumber(Images.EditMode, 0)
End Sub

No matter whic h lo c king strategy yo u c ho se, it is still po ssible fo r the update to fail.
Yo u may have c hanged the primary key so that it duplic ates ano ther value in the
table. It is po ssible that yo u may have used a set o f values that vio lates a fo reign
key c o nstraint, o r yo u may have triggered ano ther c o nstraint. In these situatio ns,
the update will no t be made to the database, and the Update metho d will fail. Yo ur
c urrent data will remain in the Fields c o llec tio n, and yo u may attempt to c o rrec t

the pro blem and try the Update metho d again.

Adding a new record
Adding a new rec o rd is similar to updating an existing rec o rd, exc ept that no lo c ks
are required. The AddNew metho d c reates a new database rec o rd by c reating an
empty ro w, whic h then bec o mes the c urrent rec o rd ( see Listing 16-3) . All o f the
Field o bjec ts will auto matic ally be set to Null o r the default value as spec ified in
the table definitio n. The EditMode pro perty will be set to adEditAdd, indic ating
yo u’re editing a newly ac c essed rec o rd. Yo ur pro gram is then free to c hange the
values as desired.

Listing 16-3: The Command7_Click event in
Recordset Update Demo
Private Sub Command7_Click()
On Error Resume Next
Continued

331

332


Part III ✦ Hard Core ADO

Listing 16-3: (continued)
Images.AddNew
If Err.Number 0 Then
WriteError
End If
Text10.Text = FormatNumber(Images.EditMode, 0)
End Sub

When yo ur pro gram is ready to save the new rec o rd to the database, yo u need to
c all the Update metho d. The new rec o rd will be sent to the database server fo r pro c essing. If yo u have an identity field, its value will be c o mputed befo re it is saved to
the database. If there are any erro rs with the values in the rec o rd, suc h as a duplic ate primary key, invalid fo reign key referenc e, no t Null c o nstraints, o r any o ther
c o nstraint vio latio ns, an erro r will be returned, and the rec o rd wo n’t be added.
Ho wever, the values will remain in the Fields c o llec tio n, and yo u c an c o rrec t
them to try again. Alternately, yo u c an c all the Cancel metho d to undo the AddNew
metho d.
The newly added rec o rd may o r may no t be visible in the Recordset depending o n
yo ur pro vider and the c urso r type. Yo u may have to use the ReQuery metho d to
make it visible.
Note

Yet another way to add: If you specify a list of field nam es and their values as part
of the call to AddNew, the new record w ill be created, the listed values w ill be
applied to their associated fields, and the record w ill be saved to the database.
There’s no need to call the Update m ethod. Note that this m ethod m ay still fail for
the reasons I discussed earlier, at the end of “Updating an existing record.”

Deleting an existing record
Deleting the c urrent rec o rd is as easy as c alling the Delete metho d (see Listing
16-4). Of c o urse, yo u must lo c k the rec o rd befo re deleting it, so it is po ssible fo r
the Delete metho d to fail if yo u are using o ptimistic lo c king. It is also po ssible
fo r the Delete metho d to fail if deleting the rec o rd wo uld trigger a c o nstraint.
Onc e the rec o rd is deleted, it remains the c urrent rec o rd, altho ugh if yo u try to
ac c ess any o f the Field o bjec ts, a run-time erro r will o c c ur. As so o n as yo u mo ve
the c urrent rec o rd po inter to ano ther rec o rd, the deleted rec o rd will no lo nger be
visible. Onc e a rec o rd has been deleted, yo u c an’t undelete it using the Cancel
metho d.

Chapter 16 ✦ Working with Recordsets —Part III

Listing 16-4: The Command8_Click event of
Recordset Update Demo
Private Sub Command8_Click()
On Error Resume Next
Images.Delete
If Err.Number 0 Then
WriteError
End If
Text10.Text = FormatNumber(Images.EditMode, 0)
End Sub

The Delete metho d has an interesting c apability that allo ws yo u to delete multiple
ro ws with a single c all. Yo u c an delete all o f the ro ws in the Recordset, o r yo u c an
delete o nly tho se rec o rds selec ted by the Filter pro perty. Yo u c an also delete the
ro ws in the c urrent c hapter o f a hierarc hic al rec o rdset.

Performing batch updates
The idea behind o ptimistic lo c king is that with eno ugh data, the o dds that two o r
mo re peo ple wo uld try to ac c ess the same rec o rd are so lo w as to be no nexistent.
Suppo se yo u have an applic atio n that falls into this gro up that perfo rms o peratio ns
o n gro ups o f rec o rds rather than just individual rec o rds. Perhaps, yo u have a table
that yo u use to ho ld the line items entry fro m an o rder. So if so meo ne is likely to
ac c ess o ne o f these ro ws, that perso n is likely to ac c ess all o f them. The same argument c o uld ho ld true fo r the c o urse rec o rds in a student info rmatio n system, the
transac tio n rec o rds against a single financ ial ac c o unt, o r the payro ll rec o rds o f
a single emplo yee. Eac h o f these gro ups c o uld be c o nsidered a batc h, whic h is
updated as a single unit.
ADO suppo rts the c o nc ept o f batc h updating with a batch o ptimistic lo c king strategy. It uses the same lo c king strategy that is used fo r an o ptimistic lo c k, but it
allo ws yo u to c reate a gro up o f c hanges that are sent to the database server fo r pro c essing at a single time. By transmitting the gro up o f c hanges as a single gro up, yo u
c an get better respo nse time bec ause yo u do n’t have to wait o n eac h individual ro w
to be updated. Also , this means less wo rk fo r the server as it c an update the gro up
o f ro ws mo re intelligently.

333

334

Part III ✦ Hard Core ADO

In terms o f using batc h o ptimistic lo c ks in yo ur applic atio n, yo u need to o pen
the Recordset o bjec t with LockType equal to adLockBatchOptimistic. Next
yo u sho uld set CursorLocation to adUseClient and CursorType to adStatic.
While o ther c o mbinatio ns o f these pro perties may wo rk, these will give yo u the
best results. All o f the data will be buffered lo c ally in the c lient c o mputer, whic h
will give yo u the best perfo rmanc e bec ause yo u o nly c o mmunic ate with the database server at the beginning and the end o f the pro c ess.
After yo u o pen yo ur Recordset, yo u c an use it as yo u no rmally wo uld. Yo u c an add
new rec o rds, delete existing o nes, o r c hange any values yo u c ho o se. Ho wever, as
yo u make these c hanges, they are held and no t transmitted to the database server
fo r pro c essing. Instead, they are held lo c ally until yo u explic itly c o mmit them o r
disc ard them.
Yo u c an disc ard yo ur c hanges with the CancelBatch metho d (see Listing 16-5), o r
yo u c an save the c hanges with the UpdateBatch metho d (see Listing 16-6). Ho wever,
sinc e the c hanges are applied with an o ptimistic lo c k, yo u need to c hec k fo r erro rs to
see if all o f yo ur c hanges were suc c essfully applied. Even if yo u use the CancelBatch
metho d, it is po ssible fo r yo u to get a warning o r an erro r if so meo ne else deleted
so me o r all o f the rec o rds yo u wo uld have updated befo re yo u c anc eled the update.

Listing 16-5: The Command13_Click event in Recordset
Update Demo
Private Sub Command13_Click()
On Error Resume Next
Images.CancelBatch
If Err.Number 0 Then
WriteError
End If
Text10.Text = FormatNumber(Images.EditMode, 0)
End Sub

Yo u c an c hec k the status o f yo ur data after yo u use the CancelBatch o r the
UpdateBatch by setting the Filter pro perty to adFilterConflictingRecords.
The filter limits the rec o rdset so that o nly the rec o rds that c o uldn’t be updated during the c all to UpdateBatch are visible. Yo u sho uld then sc an thro ugh the entire
rec o rdset and c hec k the Status pro perty to learn why the rec o rds weren’t pro perly updated.

Chapter 16 ✦ Working with Recordsets —Part III

Listing 16-6: The Command11_Click event in Recordset
Update Demo
Private Sub Command11_Click()
On Error Resume Next
Images.UpdateBatch
Images.Filter = adFilterConflictingRecords
Images.MoveFirst
Do While Not Images.EOF
If Images.Status 0 Then
MsgBox “Error “ & FormatNumber(Images.Status,0) & _
“ in: “ & _
FormatNumber(Images.Fields(“InventoryId”).Value, 0)
End If
Images.MoveNext
Loop
Text10.Text = FormatNumber(Images.EditMode, 0)
End Sub

M aking Transactions
An impo rtant feature in ADO is the ability to use transactio ns while pro c essing yo ur
data. They allo w yo u to identify a series o f individual database o peratio ns all o f
whic h must be suc c essful o r all o f their effec ts must be c o mpletely remo ved fro m
the database.

Why do I need transactions?
Think bac k to Chapter 14 where I was disc ussing why lo c king is nec essary in a
database system. I disc ussed an example where yo u needed to serialize the debits
and the c redits to a bank ac c o unt to prevent an invalid value fro m being c reated.
Yet yo u c o uld c reate an invalid amo unt in ano ther way, even with pro per lo c king.
Co nsider what happens when yo u transfer mo ney fro m o ne ac c o unt to ano ther. Yo u
withdraw mo ney fro m o ne ac c o unt and c redit it to ano ther. With lo c king, yo u c an
make sure that eac h o peratio n ensures that the appro priate values are c reated in
bo th tables. Ho wever, what happens if o ne o peratio n happens and the o ther do es-

335

336

Part III ✦ Hard Core ADO

n’t. If yo u do the withdrawal first, the mo ney will disappear if it isn’t pro perly c redited, while if the c redit is made first, the mo ney appears to c o me o ut o f no where.
This is a situatio n where yo u have two database o peratio ns that must be suc c essful
o r bo th o peratio ns must fail to gether. If o nly o ne fails, yo u have a serio us pro blem.
The pro blems that c ause the failure o f o ne o peratio n and no t the o ther c an range
fro m a simple applic atio n erro r, thro ugh a netwo rking pro blem, and to a majo r
database server pro blem. While yo u might think that this example is a little c o ntrived, there are many situatio ns where yo u have a series o f database o peratio ns
where yo u want all o f them to suc c eed o r no ne o f them.
The so lutio n to this pro gram is to gro up the set o f o peratio ns into a pac kage kno wn
as a transac tio n. A transac tio n is an ato mic unit bec ause it c an’t be subdivided. The
entire transac tio n must be applied to the database, o r the entire transac tio n is
abo rted.
Yet a transac tio n need no t be limited to a single rec o rdset. Mo st applic atio ns
update multiple rec o rdsets as a ro utine part o f their pro c essing. Co nsider the
o rder po rtio n o f the sample database. The Orders table c o ntains info rmatio n that
is spec ific to the o rder suc h as the Custo merId and the date the o rder was plac ed.
Eac h item in the o rder has a separate rec o rd in the OrderDetails table. To plac e an
o rder, yo u have to add o ne rec o rd to the Orders table and o ne o r mo re rec o rds to
the OrderDetails table. This is ano ther situatio n where yo u want bo th tables pro perly updated o r neither.

ADO and transactions
Transac tio ns are implemented using the Connection o bjec t and no t the Recordset
o bjec t. Yo u c an invo lve any number o f Recordset o bjec ts and o peratio ns as lo ng as
they are all using the same Connection o bjec t. Of c o urse, the single c o nnec tio n limitatio n implies that a transac tio n c an’t span mo re than o ne database server, tho ugh
yo u may be able to ac c ess multiple databases o n a single database server.
A transac tio n invo lves three basic metho ds. The BeginTrans metho d (see Listing
16-7) marks the beginning o f a transac tio n. The CommitTrans metho d (see Listing
16-8) marks the suc c essful c o nc lusio n o f a transac tio n, while the RollbackTrans
metho d (see Listing 16-9) disc ards all o f the c hanges made and leaves the database
unto uc hed.
Note

Transactions aren’t batch locks: Don’t confuse batch optim istic locks w ith transactions. They serve tw o different purposes. Batch optim istic locks are a perform ance enhancem ent that can be used successfully on large databases w here you
don’t expect m ultiple users to try to access the sam e group of row s. Transactions
are used to ensure that the database rem ains consistent. They can be used in any
situation w here you have a group of database operations that m ust be perform ed
together or not at all.

Chapter 16 ✦ Working with Recordsets —Part III

Listing 16-7: The Command21_Click event in Recordset
Update Demo
Private Sub Command21_Click()
On Error Resume Next
db.BeginTrans
If Err.Number 0 Then
WriteError
Else
Text11.Text = “Active”
End If
End Sub

Listing 16-8: The Command20_Click event in Recordset
Update Demo
Private Sub Command20_Click()
On Error Resume Next
db.CommitTrans
If Err.Number 0 Then
WriteError
Else
Text11.Text = “Committed”
End If
End Sub

Listing 16-9: The Command19_Click event in R
ecordset Update Demo
Private Sub Command19_Click()
On Error Resume Next
db.RollbackTrans
If Err.Number 0 Then
Continued

337

338

Part III ✦ Hard Core ADO

Listing 16-9 (continued)
WriteError
Else
Text11.Text = “Rollback”
End If
End Sub

If yo u set the Connection o b jec t’s Attribute pro perty to either adXactAbort
Retaining o r adXactCommitRetaining o r b o th, a new transac tio n will b e
started auto matic ally when yo u c all either the RollbackTrans o r the Commit
Trans metho d. While this c an b e useful in so me types o f pro grams, I like the idea
o f explic itly marking the b eginning and end o f a transac tio n. No t o nly do es this
make the c o de that fo rms the transac tio n c learer to the next pro grammer who
may have to mo dify yo ur pro gram, b ut it also allo ws yo u the freedo m to perfo rm
datab ase ac tivities o utside the sc o pe o f a transac tio n.

Working with Disconnected Recordsets
Client-side c urso rs let yo u do mo re o f yo ur datab ase wo rk o n yo ur lo c al mac hine
rather than c o ntinually c o mmunic ating with the datab ase server fo r eac h and
every req uest. Ho wever, it is po ssib le to do all o f yo ur wo rk lo c ally if yo u’re willing to do a little extra wo rk and then uplo ad yo ur wo rk to the datab ase server
when yo u’re finished.
What is a disc o nnec ted rec o rdset? The basic idea behind a disco nne cte d re co rdse t is
that yo u make a lo c al c o py o f the data in the rec o rdset and then break the c o nnec tio n to the database server. Yo u c an then perfo rm yo ur updates against the lo c al
c o py, and when yo u’re finished, yo u c an rec o nnec t to the database server and
uplo ad the c hanges.
The key to making this wo rk is the ability to use a c lient-side c urso r and batc h o ptimistic lo c king. Using these to o ls, yo u wo uld go ahead and pro c ess yo ur data no rmally
and all o f the c hanges wo uld be buffered lo c ally until yo u exec ute the UpdateBatch
metho d to transmit them to the database server. So while yo u might have a c o nnec tio n to the database server, it’s no t abso lutely nec essary sinc e there are no c o mmunic atio ns traveling between the database c lient and the database server.
Tip

Disconnected from the net: Disconnected recordsets are ideal for situations
w here you need to m ake changes to your database from a laptop that is not perm anently attached to your netw ork. You can collect these changes into a single
batch w hile the com puter is aw ay from the netw ork and upload them w hen the
com puter is reattached to the netw ork.

Chapter 16 ✦ Working with Recordsets —Part III

M aking a recordset local
A Recordset o bjec t c an be saved as a lo c al disk file by using the Save metho d. Yo u
c an save the rec o rdset using either the ADTG (Advanc ed Data Table Datagram) o r
XML (Extensible Markup Language). ADTG is a Mic ro so ft pro prietary fo rmat that is
so mewhat mo re effic ient than the XML fo rmat and c an handle all types o f Record
sets. XML is an o pen standard suppo rted by multiple vendo rs, but there are so me
situatio ns (primarily dealing with hierarc hic al rec o rdsets) where yo u may lo se so me
func tio nality. When saving a Recordset fo r lo c al pro c essing, either fo rmat is fine,
tho ugh XML wo uld be preferred if yo u want to share the file with so meo ne else.

Saving the recordset
In the example in Listing 16-10, I c o nstruc ted a filename using the direc to ry path
to the applic atio n and the first three c harac ters o f the file type desc ribed in the
c o mbo bo x. Then I used the value fro m the ItemData list fo r the c urrent c o mbo
bo x to determine the fo rmat used to save the Recordset.

Listing 16-10: The Command18_Click event of
Recordset Update Demo
Private Sub Command18_Click()
On Error Resume Next
Images.Save App.Path & “\localrs.” &
Left(Combo5.Text, 3), _
Combo5.ItemData(Combo5.ListIndex)
If Err.Number 0 Then
WriteError
End If
End Sub

Note

Expensive words: The process of saving a copy of a Recordset locally so it can
be reopened w hile not connected to the database server is know n as persisting
the recordset.

CrossReference

I’ll talk about XML in m ore detail starting w ith Chapter 21.

Onc e the Recordset has been saved, yo u c an disc o nnec t it fro m the database
server by setting the ActiveConnection pro perty to Nothing. Then yo u c an c lo se
the Recordset o bjec t and the Connection o bjec t. As lo ng as the rec o rdset is c o nnec ted to the database, yo u will c o ntinue to o perate as befo re.

339

340

Part III ✦ Hard Core ADO

Opening the saved recordset
Onc e yo u have saved the Recordset as just desc ribed, yo u c an reo pen it using the
file yo u just saved witho ut spec ifying a c o nnec tio n to the database server (see
Listing 16-11). Yo u’ll need a valid instanc e o f a Recordset o bjec t in o rder to o pen
the file. When yo u c o de the Open metho d, yo u need to spec ify the name o f the file
as the Source parameter and adCmdFile fo r the Options parameter. The file will
then be c o pied by the c lient c urso r library into memo ry and c an be ac c essed as a
no rmal Recordset o bjec t, and yo u c an also use bo und c o ntro ls.

Listing 16-11: The Command22_Click event of the Recordset
Update Demo
Private Sub Command22_Click()
On Error Resume Next
If Images Is Nothing Then
Set Images = New Recordset
Else
Images.Close
End If
Err.Clear
Images.Open App.Path & “\localrs.” & Left(Combo5.Text, 3), , _
adOpenStatic, adLockBatchOptimistic, adCmdFile
If Err.Number 0 Then
WriteError
Else
Text8.Text = “Local”
Text4.DataField = “InventoryId”
Set Text4.DataSource = Images
Text7.DataField = “Seq”
Set Text7.DataSource = Images
Image1.DataField = “Image”
Set Image1.DataSource = Images
End If
End Sub

Chapter 16 ✦ Working with Recordsets —Part III

Reconnecting to the database server
Onc e yo u’ve finished updating yo ur rec o rdset lo c ally, yo u need to rec o nnec t to the
database server. This c an be a few minutes o r a few days after yo u o riginally saved
the data. If yo u haven’t o pened the rec o rdset with batc h o ptimistic lo c ks, yo u need
to c lo se the rec o rdset and reo pen it.
With the o pen c o py o f the lo c al rec o rdset, yo u then have to set the Active
Connection pro perty to a valid c o nnec tio n o bjec t (see Listing 16-12). This will
resto re yo ur c o nnec tio n to the database server. Then yo u c an use the UpdateBatch
metho d to send the c hanged rec o rds to the database server. It is very impo rtant
that yo u c hec k the results o f the UpdateBatch metho d; sinc e it is po ssible so meo ne else may have updated the rec o rds while yo u were editing the rec o rdset lo c ally.

Listing 16-12: The Command25_Click event in
Recordset Update Demo
Private Sub Command25_Click()
On Error Resume Next
Set Images.ActiveConnection = db
If Err.Number 0 Then
WriteError
End If
Images.UpdateBatch
Images.Filter = adFilterConflictingRecords
Images.MoveFirst
Do While Not Images.EOF
If Images.Status 0 Then
MsgBox “Error “ & FormatNumber(Images.Status,0) & _
“ in: “ & _
FormatNumber(Images.Fields(“InventoryId”).Value, 0)
End If
Images.MoveNext
Loop
End Sub

341

342

Part III ✦ Hard Core ADO

Working with Other Recordset Functions
There are few o ther func tio ns available fo r rec o rdsets, whic h I want to briefly to uc h
o n in this c hapter. Fo r the mo st part, these func tio ns aren’t used very o ften, but
they c an add value to yo ur applic atio n in the right situatio n.

Cloning a recordset
So metimes it is useful to c reate an identic al c o py o f a Recordset o bjec t. This may
arise if yo u need multiple c urrent rec o rd po inters in the same rec o rdset o r if yo u
want to use two different filters at the same time.
In o rder to c lo ne a rec o rdset, yo ur pro vider must suppo rt bo o kmarks. The side
effec t o f this is that a bo o kmark fro m o ne rec o rdset will wo rk in all o f its c lo nes as
lo ng as no filters have been applied o r yo u haven’t exec uted the Resync o r Requery
metho ds. This has yet ano ther side effec t; c hanges made to o ne rec o rdset will be
seen immediately by the o ther rec o rdsets.

Resyncing and requerying a recordset
When yo u ac c ess a Recordset with a static o r fo rward-o nly c urso r, yo u c an’t
see the c hanges that so meo ne else may have made in the datab ase. The Resync
metho d allo ws yo u to get a fresh c o py o f the values fro m the datab ase witho ut
exec uting the q uery again. This means that the Resync metho d is mo re effic ient.
Of c o urse, Resync has its limitatio ns. It wo n’t detec t when a new rec o rd has been
added. If any o f the rec o rds in the Recordset are deleted, an erro r will be generated in the Error c o llec tio n, and yo u will need to use the Filter pro perty to
examine these rec o rds to determine ho w yo u want to handle them.
The Requery metho d o n the o ther hand fo rc es the database server to re-exec ute
the query that was o riginally used to retrieve the rec o rds fro m the database. This
means that rec o rds that have been added, deleted, and updated will be pro perly
reflec ted in yo ur Recordset. Calling Requery is the equivalent o f c alling the Close
and Open metho ds. Obvio usly, using Requery is mo re expensive (in terms o f
reso urc es and time) than using Resync, but there are times when it is nec essary.

Returning multiple recordsets
A sto red pro c edure has the ability to return multiple rec o rdsets with a single c all;
ho wever, o nly o ne rec o rdset is ac c essible at a time thro ugh the Recordset o bjec t.
Yo u c an also spec ify multiple Select statements in a Command o bjec t to return multiple rec o rdsets.

Chapter 16 ✦ Working with Recordsets —Part III

When yo u exec ute the Command o bjec t, the first rec o rdset is generated, and the
server waits to generate the next rec o rdset until yo u c all the NextRecordset
metho d. If yo u c lo se the Recordset o bjec t befo re retrieving all o f the rec o rdsets,
the remaining statements are no t exec uted.

Alternate ways to get data
While yo u c an retrieve info rmatio n fro m a rec o rdset using the Fields c o llec tio n,
there are a c o uple o f o ther metho ds o f whic h yo u sho uld be aware. They are the
GetRows metho d and the GetString metho d. Bo th return o ne o r mo re ro ws o f
info rmatio n fro m the Recordset o bjec t in a single c all.
The GetRows metho d returns a Variant c o ntaining a two -dimensio nal array where
eac h ro w o f the array c o rrespo nds to a ro w o f info rmatio n fro m the rec o rdset and
eac h c o lumn o f the array c o rrespo nds to a c o lumn in the rec o rdset. The dimensio ns o f the array are auto matic ally resized to handle the amo unt o f data that yo u
request.
Yo u c an also spec ify the field yo u want to extrac t by inc luding the name o f the field
as a parameter to the metho d. Yo u c an spec ify an array c o ntaining list o f fields that
yo u want to retrieve.
The GetString metho d perfo rms the same basic func tio n as the GetRows metho d,
but it returns the data as a single String rather then the c ells o f an array. Yo u c an
spec ify the delimiter that will be used between c o lumns and the delimiter between
ro ws. Fo r example, yo u c an c reate a CSV (c o mma separated value) file by spec ifying
a c o mma ( ,) as the c o lumn delimiter and a c arriage return/ line feed pair ( vbCrLf)
fo r the ro w delimiter.
Bo th metho ds start with the c urrent rec o rd and return the spec ified number o f
rec o rds. The GetRows metho d allo ws yo u to spec ify the starting po sitio n if yo ur
Recordset suppo rts bo o kmarks.
Tip

Comma Separated Value files, the easy way: The GetString m ethod m akes it
really easy to create the data for a CSV file.

No te that with either metho d, yo u may get an erro r numb er 3021 when reading
the last b lo c k o f data. This erro r numb er means that yo u reac hed the end o f the
file; ho wever, this is expec ted, if yo u read multiple rec o rds at a time. In this c ase,
it means that yo u req uested mo re rec o rds than were availab le, henc e the end o f
file erro r.

343

344

Part III ✦ Hard Core ADO

Setting the cache size
One o f the pro blems when building a c lient/ server database is that all o f the c o mmunic atio ns between the c lient pro gram and the database server are ro uted thro ugh a
netwo rk. By default, o nly o ne rec o rd is transmitted between yo ur applic atio n and
the database server eac h time yo u mo ve the c urrent rec o rd po inter. Ho wever, this
value is tunable by using the CacheSize pro perty.
The CacheSize determines the number o f rec o rds that are buffered lo c ally by the
OLE DB pro vider. A value o f o ne means that o nly o ne rec o rd is quic kly available to
yo ur pro gram. Inc reasing this size to mo re than o ne means that the pro vider will
keep multiple rec o rds lo c ally. This means that the pro vider will no t request additio nal data fro m the server until yo u referenc e a rec o rd o utside o f the c ac he. As lo ng
as yo ur pro gram requests fro m within the c ac he, the pro vider do esn’t need to c o mmunic ate with the database server. When yo ur pro gram do es referenc e a rec o rd o utside o f the c ac he, the pro vider will flush the lo c al c ac he and fill it again with new
rec o rds fro m the database server.
Depending o n yo ur pro gram, c hanging the CacheSize pro perty c an make a big differenc e, either go o d o r bad. If yo u are reading thro ugh the Recordset sequentially, then
yo u’ll get the biggest perfo rmanc e bo o st, espec ially if yo u o pen the rec o rdset in reado nly mo de with a fo rward-o nly c urso r. In many c ases, the c o st o f retrieving rec o rds is
pro po rtio nal to the number o f c alls the pro vider has to make to the database server.
Thus, if yo u retrieve mo re rec o rds fro m the database server with eac h c all, the fewer
c alls yo u will need to make to satisfy the query.
Ho wever, if yo ur pro gram is reading rec o rds rando mly thro ugho ut the rec o rdset,
having a large c ac he is a detriment. The database server must retrieve mo re
rec o rds fro m the database and transmit them o ver the netwo rk, whic h is wo rk that
is essentially wasted.
There is ano ther issue using a large c ac he, whic h c an c ause o ther pro blems if yo u
are no t c areful. Sinc e the pro vider and server are no t in c o ntac t until yo u need to
retrieve additio nal rec o rds, it is po ssible that so meo ne else will have c hanged o r
deleted a rec o rd after the rec o rds were retrieved. Yo ur pro gram will need to be able
to handle this situatio n. Fo r read-o nly ac c ess with a fo rward-o nly c urso r, this
sho uldn’t be a big pro blem. But if yo ur pro gram is attempting to update rec o rds
using a CacheSize greater than o ne, yo u may have pro blems. I suggest that yo u
either use batc h o ptimistic lo c king and handle the erro rs after the fac t o r dro p the
CacheSize bac k to o ne.

Chapter 16 ✦ Working with Recordsets —Part III

Thoughts on Updating Recordsets
Updating Recordsets is one of the m ost im portant functions that a database program
PERFORMS. ADO provides a w ide range of tools to m ake this process as painless as possible. Once you get com fortable using the ADO object library to access your data, using other
tools w ill feel dow nright aw kw ard.
Most of the tim e w hen I need to build a sim ple program to update a database, I just open
a Recordset object and then bind a bunch of controls to it to display the inform ation.
While there is a little m ore code involved w ith this process than using som ething like the
ADO Data Control, I don’t m ind the extra w ork because I prefer to open the Recordset
after I open the form that uses it.
But w hile it is easy to update a database using a Recordset, you’ll probably be better off
using stored procedures and a Command object. Depending on the database server and the
OLE DB provider, m any Recordset operations have to be translated to explicit SQL
Statem ents that are executed directly against the database. While this extra w ork isn’t
m uch, if you have a high-volum e application, anything you can do to reduce w ork w ill m ake
your application run better. After all, w hile m achine resources are relatively cheap, som eone has to pay for them , and if you don’t really need the resources, you shouldn’t use them .

Summary
In this c hapter yo u learned the fo llo wing:

✦ Yo u c an c hange the values in a ro w by using the Fields c o llec tio n and then
save the new values using the Update metho d.

✦ Yo u c an use the AddNew metho d to insert a new ro w and the Delete metho d
to remo ve a ro w fro m a rec o rdset.

✦ Yo u c an gro up c hanges into batc hes fo r better perfo rmanc e.
✦ Yo u c an define transac tio ns in yo ur applic atio n, in whic h all o f the c hanges
must suc c eed o r all o f the c hanges will be disc arded.

✦ Yo u c an use disc o nnec ted rec o rdsets to ac c ess info rmatio n fro m the database
witho ut having an ac tive c o nnec tio n to the database.

✦ Yo u c an perfo rm a number o f o ther useful func tio ns with a Recordset o bjec t
suc h as returning multiple rec o rdsets and multiple ro ws.







345