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

14

C H A P T E R

Working with
Recordsets —
Part I









In This Cha pter
The Reco rdset o bject

O


f all o f the o bjec ts in ADO, the Recordset o bjec t is the
o ne yo u’ll use the mo st. It c o ntains the ac tual data fro m
yo ur database. Yo u c an use this o bjec t to retrieve, insert,
update, and delete info rmatio n fro m the database. It c an be
used as a data so urc e fo r o ther c o ntro ls, just like the ADO
Data Co ntro l. In fac t the ADO Data Co ntro l expo ses a referenc e to the Recordset o bjec t, yo u c an ac c ess the info rmatio n
c o ntained in the underlying rec o rdset direc tly.

This c hapter and the next two are dedic ated to the to pic o f
rec o rdsets. In this c hapter, I’m go ing to disc uss the vario us
pro perties, metho ds, and events in a Recordset o bjec t. Then
I’ll disc uss ho w to o pen and use a Recordset o bjec t. In the
next c hapter, I’ll c o ntinue disc ussing the Recordset o bjec t
and c o ver ho w to mo ve aro und inside rec o rdsets and ho w to
ac c ess the individual fields. Finally, in Chapter 16 I’ll c o ver the
issues related to updating the data c o ntained in a rec o rdset.

The Recordset Object
The Recordset o bjec t c o ntains the set o f ro ws retrieved fro m a
database query. Vario us pro perties and metho ds instruc t the

OLE DB pro vider o n ho w the ro ws sho uld be returned fro m the
database and ho w the pro vider sho uld handle updates and
lo c king to ensure pro per ac c ess to the data. Other pro perties
and metho ds in the Recordset o bjec t allo w yo u to ac c ess the
set o f ro ws retrieved.

Explo ring vario us
types o f lo cks
Cho o sing a
curso r type
O pening a reco rdset










266

Part III ✦ Hardcore ADO

Note

Birds of a Feather aren’t at the first record of the Recordset: There is a com m on
m isconception that w hen BOF is TRUE, you are at the first record of the
Recordset. This isn’t true. When BOF is TRUE, the current record pointer is before
the first record in the Recordset, and there isn’t a current record. The sam e is
true for EOF, except in that case, the current record pointer is beyond the last
record in the Recordset.

Recordset object properties
Table 14-1 lists the pro perties asso c iated with the Recordset o bjec t. Tables 14-2
thro ugh 14-8 c o ntain additio nal info rmatio n abo ut individual pro perties in the
Recordset o bjec t.

Table 14-1
Properties of the Recordset Object

Property

Description

AbsolutePage

A Long value containing the absolute page num ber of the
current record in the Recordset ranging from 1 to PageCount.
This value m ay also be adPosBOF (-2) if the current record is at
the beginning of the file or adPosEOF (-3) if the current record
is at the end of the file. A value of adPosUnknown (-1) m ay be
used if the Recordset is em pty or the provider doesn’t support
this property.

AbsolutePosition

A Long value containing the absolute position of the current
record in the Recordset ranging from 1 to RecordCount. This
value m ay also be adPosBOF (-2) if the current record is at the
beginning of the file or adPosEOF (-3) if the current record is at

the end of the file. A value of adPosUnknown (-1) m ay be used
if the Recordset is em pty or the provider doesn’t support this
property.

ActiveCommand

An object reference to the Command object that created the
Recordset. If the Recordset w asn’t created using a Command
object, this property w ill have a Null object reference.

ActiveConnection

A Variant array containing either a String value w ith a valid
connection string or an object reference to a Connection
object.

BOF

A Boolean value that is TRUE w hen the current record position
is before the first record in the Recordset.


Chapter 14 ✦ Working with Recordsets —Part I

Property

Description

Bookmark

A Variant that sets or returns a value that uniquely identifies
the current record in the current Recordset object. You can
save this property and m ove to a different record. Then you can
restore the value to return back to the original record.

CacheSize

A Long value containing the num ber of records kept in the
provider’s cache. The default value for this property is 1.

CursorLocation


An enum erated value that indicates w here the cursor is
m aintained (see Table 14-2).

CursorType

An enum erated value that specifies the type of cursor that w ill
be used on the Recordset. (see Table 14-3).

DataMember

A String containing the nam e of the data m em ber that w ill be
retrieved using the DataSource property. Works w ith the
DataSource property to bind a Recordset to a control.

DataSource

An object reference that indicates the data source w hen using
bound controls.


EditMode

An enum erated value containing the edit m ode of the current
record (see Table 14-4).

EOF

A Boolean value that is TRUE w hen the current record position
is after the last record in the Recordset.

Fields

An object reference to a Fields collection containing the fields
associated w ith the current record.

Filter

A Variant value containing one of the follow ing: a String
value containing an expression sim ilar to that in a Where clause
that w ill select only those records m eeting the specified criteria;

an Array of bookm arks; or a Long value selected from Table
14-5.

Index

A String containing the nam e of an index that is used in
conjunction w ith the Seek m ethod.

LockType

An enum erated value containing the locking m ode used by the

Recordset w hen retrieving records (see Table 14-6).
MarshalOptions

An enum erated value that indicates how records are to be
m arshaled back to the server. Applies only to Recordsets w ith
client-side cursors (discussed later in this chapter). The default
value is adMarshalAll (0), w hich returns all row s back to the
server for processing, w hile adMarshalModifiedOnly (1)

returns only the m odified row s.
Continued

267

268

Part III ✦ Hardcore ADO

Table 14-1 (continued)
Property

Description

MaxRecords

A Long value that specifies the m axim um num ber of row s to be
returned. A value of zero im plies there is no m axim um lim it.

PageCount


A Long value containing the num ber of pages of data in the
Recordset. The num ber of records in a page is specified by the
PageSize property, w hile the current page num ber is specified
in the AbsolutePage property.

PageSize

A Long value containing the num ber of records in a single page.

Properties

An object reference to a Properties collection containing
provider specific inform ation.

RecordCount

A Long value containing the num ber of records retrieved. If the
provider is not able to determ ine the num ber of records
retrieved or a forw ard-only cursor is selected, this property w ill
have a value of –1.

Sort

Specifies a list one or m ore of field nam es on w hich the
Recordset w ill be sorted. Multiple fields need to be separated
by com m as, and each field nam e m ay be follow ed by ASC or
DESC to sort the fields in either ascending or descending order.
The syntax is basically the sam e as the Order By clause in the
Select statem ent. This property is only valid w hen you use a
client-side cursor (discussed later in this chapter).

Source

A Variant w hich can either be a String containing the nam e
of a table, a SQL Statem ent, or the nam e of a stored procedure
or an object reference to a Command object.

State

A Long value describing the current state of the Recordset
object. Multiple values can be com bined to describe the current
state (see Table 14-7 for a list of values).

Status

A Long value describing the current status of a record in a batch
update (see Table 14-8).

StayInSync

A Boolean value that w hen TRUE m eans that the reference to
child records in a hierarchical Recordset w ill autom atically be
changed w hen the parent row ’s position changes. The default
value for this property is TRUE.

Chapter 14 ✦ Working with Recordsets —Part I

Table 14-2
Values for CursorLocation
Constant

Value

Description

adUseNone

1

Doesn’t use cursor services. This value should not
be selected and exists solely for com patibility.

adUseServer

2

The cursor services are provided by the data
provider.

adUseClient

3

The cursor services are provided by a local cursor
library, w hich m ay provide m ore features than
the data provider’s cursor library provides.

Table 14-3
Values for CursorType
Constant

Value

Description

adOpenUnspecified

-1

The type of cursor isn’t specified.

adOpenForwardOnly

0

A forw ard-only cursor is used, w hich perm its you
only to scroll forw ard through the records in the
Recordset.

adOpenKeyset

1

A keyset cursor is used, w hich is sim ilar to a
dynam ic cursor, but doesn’t perm it you to see
records added by other users.

adOpenDynamic

2

A dynam ic cursor is used, w hich allow s you to
see records added by other users, plus any
changes and deletions m ade by other users.

adOpenStatic

3

A static cursor is used, w hich prevents you from
seeing any and all changes from other users.

269

270

Part III ✦ Hardcore ADO

Table 14-4
Values for EditM ode
Constant

Value

Description

adEditNone

0

Editing is not active; the data in the current
record hasn’t been changed.

adEditInProgress

1

The data in the current record has been changed,
but not yet saved.

adEditAdd

2

The AddNew m ethod has been used to create a
new record, but the record hasn’t been saved yet.

adEditDelete

4

The current record has been deleted.

Table 14-5
Values for Filter
Constant

Value

Description

adFilterNone

0

Rem oves all filtering criteria.

adFilterPendingRecords

1

Selects only those records that have been
changed, but not sent to the server for
updating. Applies to batch update m ode
only.

adFilterAffectedRecords

2

Selects only those records that have been
affected by the last CancelBatch, Delete,
Resync, or UpdateBatch.

adFilterFetchedRecords

3

Selects only those records in the current
cache.

adFilterConflictingRecords

5

Selects only those records that have failed
the last batch update.

Table 14-6
Values for LockM ode
Constant

Value

Description

adLockUnspecified

-1

The type of locking isn’t specified.

adLockReadOnly

1

Doesn’t perm it you to change any values.

Chapter 14 ✦ Working with Recordsets —Part I

Constant

Value

Description

adLockPessimistic

2

Records are locked at the data source record
by record once the data in the record has
been changed.

adLockOptimistic

3

Records are locked only w hen you call the

UpdateMethod.
adLockBatchOptimistic

4

Records are not locked, and conflicts w ill be
returned for resolution after the
UpdateBatch m ethod has com pleted.

Table 14-7
Values for State
Constant

Value

Description

adStateClosed

0

The Command object is closed.

adStateOpen

1

The Command object is open.

adStateConnecting

2

The Command object is connecting to the
database.

adStateExecuting

4

The Command object is executing.

adStateFetching

8

Row s are being retrieved.

Table 14-8
Values for Status
Constant

Value

Description

adRecOK

0

The record w as successfully updated.

adRecNew

1

The record is new.

adRecModified

2

The record has been m odified.

adRecDeleted

4

The record has been deleted.

adRecUnmodified

8

The record has not been m odified.

adRecInvalid

16

The record w asn’t saved because its
bookm ark w as invalid.
Continued

271

272

Part III ✦ Hardcore ADO

Table 14-8 (continued)
Constant

Value

Description

adRecMultipleChanges

64

The record w asn’t saved because it w ould
have affected m ultiple records.

adRecPendingChanges

128

The record w asn’t saved because it refers to
a pending insert.

adRecCanceled

256

The record w asn’t saved because the
operation w as canceled.

adRecCantRelease

1024

The new record w asn’t saved because the
existing record w as locked.

adRecConcurrencyViolation 2048

The record w asn’t saved because optim istic
concurrency w as in use.

adRecIntegrityViolation

4096

The record w asn’t saved because the data
violated an integrity constraint.

adRecMaxChangesExceeded

8192

The record w asn’t saved because there w ere
too m any pending changes.

adRecObjectOpen

16384

The record w asn’t saved because of a
conflict w ith an open storage object.

adRecOutOfMemory

32768

The record w asn’t saved because the
com puter ran out of m em ory.

adRecPermissionDenied

65536

The record w asn’t saved because the user
doesn’t have sufficient perm issions.

adRecSchemaViolation

131072

The record w asn’t saved because it violates
the underlying database structure.

adRecDBDeleted

262144

The record has already been deleted from
the data source.

Recordset object methods,
The Recordset o bjec t c o ntains many different metho ds to manipulate the data in
the Recordset.

Sub AddNew ([FieldList], [Values])
The AddNew metho d is used to add a new empty rec o rd to the Recordset. This
will set the EditMode pro perty to adEditAdd. After assigning values to eac h o f
the fields, yo u c an use the Update metho d to save the c hanges. If yo u spec ify the
FieldList and Values parameters, the values are immediately saved to the
database and no c all to Update is needed.

Chapter 14 ✦ Working with Recordsets —Part I

In batc h update mo de, yo u pro c eed as abo ve. The c hanges will be saved lo c ally in
the Recordset, but no t sent to the server. After adding the last rec o rd o f the batc h,
yo u must c all the UpdateBatch metho d to save the c hanges to the database. Then
yo u sho uld set the Filter pro perty to adFilterConflicting and take the appro priate ac tio n fo r the rec o rds that weren’t po sted to the database pro perly.

FieldList is o ptio nal and is either a String value c o ntaining a single field name
o r a String Array c o ntaining a list o f field names.
Values is an o ptio nal Variant c o ntaining a single value c o rrespo nding to a single
field name o r Array o f values c o rrespo nding to the Array o f field names.

Sub Cancel( )
The Cancel metho d is used to terminate an async hro no us task started by the Open
metho d.

Sub CancelBatch ([AffectRecords As AffectEnum = adAffectAll])
The CancelBatch metho d is used to c anc el a pending batc h update. If the c urrent
rec o rd hasn’t been saved, CancelBatch will auto matic ally c all CancelUpdate to
disc ard any c hanges. As with all batc h o peratio ns, yo u sho uld verify the Status
pro perty fo r all o f the affec ted rec o rds to ensure that they were pro perly c anc eled.

AffectRecords is an enumerated type that desc ribes whic h rec o rds will be
affec ted by the c anc el o peratio n (see Table 14-9).

Table 14-9
Values for AffectRecords
Constant

Value

Description

adAffectCurrent

1

Affects only the current record in the
Recordset.

adAffectGroup

2

Affects only those records selected by the current
value of the Filter property.

adAffectAll

3

Affects all records in the Recordset.

adAffectAllChapters

4

Affects all records in all chapters of the
Recordset.

273

274

Part III ✦ Hardcore ADO

Sub CancelUpdate ( )
The CancelUpdate metho d is used to abando n all o f the c hanges made to a rec o rd
and to resto re its values to the o riginal values befo re the Update metho d is c alled.
If yo u use CancelUpdate to undo a ro w added with the AddNew metho d, the newly
added ro w will be disc arded, and the c urrent rec o rd will bec o me the ro w that was
the c urrent ro w befo re the AddNew metho d was used.

Function Clone ([LockType As LockTypeEnum =
adLockTypeUnspecified]) As Recordset
The Clone metho d is used to c reate a duplic ate o f a Recordset o bjec t. LockType
allo ws yo u to spec ify that the new Recordset o bjec t is read-o nly. The o nly permissible values are adLockUnspecified and adLockReadOnly.

Sub Close
The Close metho d c lo ses an o pen Recordset and frees all o f its asso c iated
reso urc es. If yo u are editing a rec o rd in the Recordset, an erro r will o c c ur, and the
Close metho d will be terminated. Yo u need to c all either Update o r CancelUpdate
first. If yo u are wo rking in batc h mo de, all c hanges sinc e the last UpdateBatch will
be lo st.

Sub CompareBookmarks(Bookmark1, Bookmark2) As CompareEnum
The CompareBookmarks metho d c o mpares two bo o kmarks and returns info rmatio n
abo ut their relative po sitio ns. Bo th bo o kmarks must c o me fro m the same Recordset
o bjec t o r fro m c lo nes o f the same Recordset o bjec t. Table 14-10 c o ntains a list o f
po ssible return values.

Bookmark1 and Bookmark2 are valid bo o kmarks.

Table 14-10
Values for CompareEnum
Constant

Value

Description

adCompareLessThan

0

The first bookm ark is before the second
bookm ark.

adCompareEqual

1

The tw o bookm arks are equal.

adCompareGreaterThan

2

The first bookm ark is after the second
bookm ark.

adCompareNotEqual

3

The tw o bookm arks are different and not
ordered.

adCompareNotComparable

4

The bookm arks can’t be com pared.

Chapter 14 ✦ Working with Recordsets —Part I

Sub Delete ([AffectRecords As AffectEnum = adAffectCurrent])
The Delete metho d is used to delete o ne o r mo re rec o rds fro m a Recordset
o bjec t.

AffectRecords is an enumerated type that desc ribes whic h rec o rds will be
deleted by this o peratio n (see Table 14-9). The default value is adAffectCurrent,
whic h means o nly the c urrent ro w will be deleted.

Sub Find (Criteria As String, [SkipRows As Long], [SearchDirection As
SearchDirectionEnum = adSearchForward], [Start])
The Find metho d is used to lo c ate the spec ified c riteria in a Recordset. No te that
yo u must have a valid c urrent rec o rd befo re c alling the Find metho d, so yo u may
want to c all MoveFirst befo re using this metho d.

Criteria is a String value that spec ifies a field name, a c o mpariso n o perato r, and
a value. Only o ne field name may be spec ified.
SkipRows is a Long value that spec ifies the number o f ro ws to skip relative to the
c urrent ro w befo re starting the searc h. The default value is zero , whic h means the
searc h will begin with the c urrent ro w.
SearchDirection is an enumerated type that indic ates the direc tio n o f the searc h.
Yo u c an spec ify adSearchForward (1) to searc h to the end o f the Recordset, o r
yo u c an spec ify adSearchBackward (-1) to searc h to the beginning o f the
Recordset.
Start is a Variant c o ntaining a bo o kmark fo r the first rec o rd to be searc hed.

Function GetRows ([Rows As Long = -1], [Start], [Fields]) As Variant
The GetRows metho d retrieves multiple rec o rds fro m a Recordset o bjec t into a
two -dimensio nal array.

Rows is the numb er o f ro ws to b e retrieved. The default value is adGetRowsRest
( -1) , whic h will retrieve the rest o f the ro ws in the tab le.
Start is an o ptio nal Variant c o ntaining a bo o kmark fo r the first ro w to be retrieved.
If yo u do no t spec ify values fo r bo th Rows and Start, all o f the ro ws in the table will
be retrieved.
Fields is an o ptio nal Variant c o ntaining a String with a single field name, a
String array with multiple field names, the index o f the field, o r an array o f field
index values.

275

276

Part III ✦ Hardcore ADO

Function GetString ([StringFormat As StringFormatEnum =
adClipString], [NumRows As Long = -1], [ColumnDelimiter As String],
[RowDelimiter As String], [NullExpr As String]) As String
The GetString metho d returns a String c o ntaining the values fro m the
Recordset.

StringFormat is a Long value c o ntaining the value adClipString (2). This is the
o nly legal value fo r this metho d.
NumRows is a Long value c o ntaining the number o f ro ws to be saved in the string. A
value o f –1 means that all o f the ro ws will be retrieved.
ColumnDelimiter is a String c o ntaining the delimiter to be used between eac h
c o lumn. If no t spec ified, a tab c harac ter will be used.
RowDelimiter is a String c o ntaining the delimiter to be used between eac h ro w. If
no t spec ified, a c arriage return c harac ter will be used.
NullExpr is a String c o ntaining the value to be displayed in plac e o f a null value.
If it is no t spec ified, no thing will be o utput.
Tip

To CSV or not to CSV: I often find it useful to create Com m a Separated Value files
from a database. These files can be easily im ported into a program like Excel for
analysis and testing. The GetString m ethod m akes it easy to w rite a program to
save your data into a CSV file. Sim ply specify a com m a for ColumnDelimiter
and vbCrLf for the RowDelimiter.

Sub M ove (NumRecords As Long, [Start])
The Move metho d is used to mo ve the c urrent rec o rd po inter to a different lo c atio n in the Recordset. If the Recordset is already at BOF, an attempt to mo ve
b ac kwards will generate a runtime erro r. Similarly, if the Recordset is already at
EOF, an attempt to mo ve fo rward will also generate a runtime erro r.

NumRecords is a Long value c o ntaining the number o f rec o rds to be mo ved. If a
value o f zero is spec ified, the c urrent rec o rd po inter remains unc hanged, and the
c urrent rec o rd is refreshed. A value greater than zero means that the c urrent rec o rd
po sitio n will be mo ved to the end o f the Recordset, while a value less than zero
will mo ve the c urrent rec o rd po inter to wards the beginning o f the Recordset.
Start is a Variant c o ntaining a bo o kmark that will be used as the starting po sitio n
fo r the mo ve.
Tip

Forward-NOT-only: Even if you specify a forw ard-only cursor, you can still m ove
backw ard using the Move m ethod, as long as you do not m ove beyond the
records in the current cache.

Chapter 14 ✦ Working with Recordsets —Part I

Sub M oveFirst ( )
The MoveFirst metho d mo ves the c urrent rec o rd po inter to the first rec o rd in the
Recordset.
Tip

M oveFirst first: I usually find it a good idea to call MoveFirst after opening a
Recordset to ensure that I have a valid record ready for processing.

Sub M oveLast( )
The MoveLast metho d mo ves the c urrent rec o rd po inter to the last rec o rd in the
Recordset. No te that yo u c an’t use the MoveLast metho d with a fo rward-o nly
c urso r.

Sub M oveNext ( )
The MoveNext metho d mo ves the c urrent rec o rd po inter to the next rec o rd in the
Recordset. If the c urrent rec o rd po inter is at the last rec o rd in the Recordset, the
c urrent rec o rd po inter will be mo ved to EOF. If the c urrent rec o rd po inter is already
at EOF, a c all to MoveNext will c ause a runtime erro r.

Sub M ovePrevious ( )
The MovePrevious metho d mo ves the c urrent rec o rd po inter to the previo us
rec o rd in the Recordset. If the c urrent rec o rd po inter is o n the first rec o rd in the
Recordset, the c urrent rec o rd po inter will be mo ved to BOF. If the c urrent rec o rd
po inter is already at BOF, a c all to MovePrevious will trigger a runtime erro r.

Function NextRecordset ([RecordsAffected]) As Recordset
The NextRecordset metho d c lears the c urrent Recordset o bjec t and returns the
next Recordset that resulted fro m a query o r sto red pro c edure that returned multiple Recordsets. RowsAffected is a Long value c o ntaining the number o f rec o rds
affec ted.

Sub Open ([Source As Variant], [ActiveConnection As Variant],
[CursorType As CursorTypeEnum = adOpenUnspecified], [LockType As
LockTypeEnum], [Options As Long = -1])
The Open metho d o pens a new Recordset o bjec t.

Source is a Variant c o ntaining an o bjec t referenc e to a valid Command o bjec t; an
o bjec t referenc e o f a valid Stream o bjec t c o ntaining a persistently sto red Recordset;
o r a String c o ntaining a SQL statement, a table name, the name o f a sto red pro c edure, a URL, o r the name o f a file.

277

278

Part III ✦ Hardcore ADO

ActiveConnection is a Variant that c o ntains an o bjec t referenc e to an o pen
Connection o bjec t o r a String value that c o ntains the same c o nnec tio n info rmatio n fo und in the ConnectionString pro perty.
CursorType is an enumerated value (see Table 14-11) that spec ifies the type o f c urso r that will be used o n the Recordset.
LockType is an enumerated value (see Table 14-12) c o ntaining the lo c king mo de
used by the Recordset when retrieving rec o rds.
Options o ptio nally passes o ne o f the values spec ified in Table 14-3.

Table 14-11
Values for CursorType
Constant

Value

Description

adOpenUnspecified

-1

The type of cursor isn’t specified.

adOpenForwardOnly

0

A forw ard-only cursor is used, w hich perm its
you only to scroll forw ard through the records
in the Recordset.

adOpenKeyset

1

A keyset cursor is used, w hich is sim ilar to a
dynam ic cursor, but doesn’t perm it you to see
records added by other users.

adOpenDynamic

2

A dynam ic cursor is used, w hich allow s you to
see records added by other users, plus any
changes and deletions m ade by other users.

adOpenStatic

3

A static cursor is used, w hich prevents you
from seeing any and all changes from other
users.

Table 14-12
Values for LockType
Constant

Value

Description

adLockUnspecified

-1

The type of locking isn’t specified.

adLockReadOnly

1

Doesn’t perm it you to change any values.

adLockPessimistic

2

Records are locked at the data source record
by record once the data in the record has
been changed.

Chapter 14 ✦ Working with Recordsets —Part I

Constant

Value

Description

adLockOptimistic

3

Records are locked only w hen you call the
UpdateMethod.

adLockBatchOptimistic

4

Records are not locked, and conflicts w ill be
returned for resolution after the
UpdateBatch m ethod has com pleted.

Sub Requery ([Options As Long = -1])
The Requery metho d gets a fresh c o py o f the data in a Recordset by re-exec uting
the query that o riginally generated the Recordset.

Options is a Long value that desc ribes ho w to exec ute the query. Yo u may set its
value to any c o mbinatio n o f the fo llo wing values desc ribed in Table 14-13: adAsync
Execute, adAsyncFetch, adAsynchFetchNonBlocking, and adExecuteNoRecords.
If o mitted, no ne o f these values will be selec ted.

Table 14-13
Values for Options
Constant

Value

Description

adOptionUnspecified

-1

No options are specified.

adCmdText

1

CommandText contains either a SQL
statem ent or a stored procedure call.

adCmdTable

2

CommandText contains the nam e of a
table in the database.

adCmdStoredProcedure

4

CommandText contains the nam e of a
stored procedure.

adCmdUnknown

8

The type of com m and isn’t know n.

adAsyncExecute

16

The com m and should be executed
asynchronously.

adAsyncFetch

32

After the num ber of row s specified in the
CacheSize property of the Recordset
object are returned, the rem aining row s w ill
be returned asynchronously.
Continued

279

280

Part III ✦ Hardcore ADO

Table 14-13 (continued)
Constant

Value

Description

adAsyncFetchNonBlocking

64

The m ain thread isn’t blocked w hile
retrieving row s. If the current row hasn’t
been retrieved, the current row w ill be
m oved to the end of the file.

adExecuteNoRecords

128

Indicates that the com m and w ill not return
any row s or w ill autom atically discard any
row s that are generated. Must be used w ith
either the adCmdText or
adCmdStoredProcedure values.

adCmdFile

256

CommandText is the nam e of a persistently
stored Recordset.

adCmdTableDirect

512

CommandText contains the nam e of a
database table.

Sub Resync ([AffectRecords As AffectEnum],
[ResyncValues As ResyncEnum)
The Resync metho d gets any updates to the data that may have happened while
using a static o r fo rward-o nly c urso r. Unlike the Requery metho d, the Resync
metho d do es no t re-exec ute the query asso c iated with the Recordset, so any ro ws
added sinc e the o riginal query was exec uted will no t be visible.

AffectRecords is an enumerated type that desc ribes whic h rec o rds will be
affec ted by the c anc el o peratio n (see Table 14-9).
ResyncValues is an enumerated type that determines ho w c hanged rec o rds in the
Recordset will be handled. A value o f adResyncUnderlyingValues ( 1) means
that all pending updates are saved, while a value o f adResyncAllValues ( 2)
means that all pending updates are c anc eled ( default) .

Sub Save ([Destination], [PersistFormat As PersistFormatEnum])
The Save metho d is used to save a lo c al c o py o f an o pen Recordset (inc luding any
c hild rec o rdsets asso c iated with it) to a disk file o r a Stream o bjec t. If yo u have an
ac tive filter o n the Recordset, o nly the filtered rec o rds will be saved. After the first
time yo u c all the Save metho d, yo u sho uld o mit the Destination parameter, bec ause
the destinatio n remains o pen. If yo u spec ify the same value fo r Destination a sec o nd
time, a runtime erro r will o c c ur. If yo u spec ify a different value, bo th destinatio ns will
remain o pen. Clo sing the Recordset will also c lo se the Destination.

Chapter 14 ✦ Working with Recordsets —Part I

Destination is a Variant value c o ntaining either an o bjec t referenc e to a Stream
o r a String c o ntaining the fully qualified filename where the data will be sto red.
PersistFormat is an enumerated data type who se value is either adPersistADTG
(0), whic h will save the Recordset in the Advanc ed Data TableGram (ADTG) fo rmat
(default), o r adPersistXML (1), whic h will save the Recordset using XML fo rmat.

Sub Seek (KeyValues, [SeekOption As SeekEnum])
The Seek metho d is used to mo ve the c urso r to a new lo c atio n in the Recordset. It
wo rks with the Index pro perty to searc h the spec ified index fo r a partic ular value.

KeyValues is an array o f Variant values, c o rrespo nding to the c o lumns in the
index.
SeekOption is an enumerated data type that spec ifies ho w to perfo rm the c o mpariso n (see Table 14-14).

Table 14-14
Values for SeekOption
Constant

Value

Description

adSeekFirstEQ

1

Seeks the first row w ith a key value equal to
KeyValues.

adSeekLastEQ

2

Seeks the last row w ith a key value equal to
KeyValues.

adSeekAfterEQ

4

Seeks the first row w ith a key value greater than or
equal to KeyValues.

adSeekAfter

8

Seeks the first row w ith a key value greater than
KeyValues.

adSeekBeforeEQ

16

Seeks the first row w ith a key value just less than or
equal to KeyValues.

adSeekBefore

32

Seeks the first row w ith a key value just less than

KeyValues.

Note

Clients not wanted: The Seek m ethod w ill not w ork w ith client-side cursors (discussed later in this chapter), so select adUseServer for the CursorType property.

281

282

Part III ✦ Hardcore ADO

Function Supports (CursorOptions As CursorOptionEnum) As Boolean
The Supports metho d returns TRUE if the data pro vider suppo rts the c o mbinatio n
o f values spec ified in CursorOptions. CursorOptions is a Long value who se value
is c reated by adding o ne o r mo re values o f the values listed in Table 14-15 to gether.

Table 14-15
Values for CursorOptions
Constant

Value

Description

adHoldRecords

256

The provider w ill retrieve m ore records or changes
to another position w ithout com m itting all
pending changes.

adMovePrevious

512

The provider supports the MoveFirst,
MovePrevious, Move, and GetRows m ethods to
m ove the cursor backw ards w ithout requiring
bookm arks.

adBookmark

8192

The provider supports the Bookmark property.

adApproxPosition

16384

The provider supports the AbsolutePosition
and AbsolutePage properties.

adUpdateBatch

65536

The provider supports the UpdateBatch and

Cancel batch m ethods.
adResync

131072

The provider supports the Resync m ethod.

adNotify

262144

The provider supports notifications, w hich im plies
that Recordset events are supported.

adFind

524288

The provider supports the Find m ethod.

adSeek

4194304

The provider supports the Seek m ethod.

adIndex

8388608

The provider supports the Index property.

adAddNew

16778240

The provider supports the AddNew m ethod.

adDelete

16779264

The provider supports the Delete position.

adUpdate

16779984

The provider supports the Update m ethod.

Sub Update ([Fields], [Values])
The Update metho d saves any c hanges yo u make the c urrent ro w o f a Recordset.
Yo u c an either update the ro w direc tly by ac c essing eac h field by using the
Recordset’s Fields c o llec tio n, o r yo u c an spec ify a list o f fields and their values
by using the Fields and Values pro perties.

Chapter 14 ✦ Working with Recordsets —Part I

If yo u mo ve to ano ther ro w in the Recordset, ADO will auto matic ally c all the
Update metho d to save yo ur c hanges. Yo u must explic itly c all the CancelUpdate
metho d to disc ard any c hanges yo u may have made befo re mo ving to ano ther ro w.

Fields is a Variant value c o ntaining a single field name o r a Variant array c o ntaining a list o f field names.
Values is a Variant value c o ntaining a single value o r a Variant array c o ntaining
a list o f values, who se po sitio n in the array c o rrespo nd to the field names in the
Fields parameter.
Note

All or none: You m ust specify both the Fields and Values param eters or neither. Specifying only one w ill cause an error. Also if you pass an array for Fields,
the Values property m ust also be an array of an identical size.

Sub UpdateBatch ([AffectRecords As AffectEnum])
The UpdateBatch metho d saves all pending batc h c hanges to the database.
AffectRecords is an enumerated data type indic ating whic h ro ws in the
Recordset will be affec ted (see Table 14-9).
Caution

It sort of worked: You m ust check the Errors collection after perform ing a
UpdateBatch to determ ine w hich row s w eren’t properly updated. You can set
the Filter property to adFilterAffectedRecords and m ove though the
rem aining records to identify those w ith problem s by checking the Status
property.

Recordset object events
The Recordset o bjec t c o ntains many different events to handle vario us c o nditio ns
enc o untered in the Recordset.

Event EndOfRecordset (fM oreData As Boolean, adStatus As
EventStatusEnum, pRecordset As Recordset)
The EndOfRecordset event is triggered when the pro gram attempts to mo ve beyo nd
the end o f the Recordset. This is mo st likely triggered by a c all to MoveNext. Yo u c an
use this event to ac quire mo re ro ws fro m the database and append them to the end
o f Recordset to allo w the MoveNext to suc c eed. If yo u do this, yo u must set the
fMoreData parameter to TRUE to indic ate that the c urso r is no lo nger at the end o f
the Recordset.

fMoreData is a Boolean value where TRUE means that mo re ro ws have been added
to the Recordset.

283

284

Part III ✦ Hardcore ADO

adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16). When the event is triggered, this value
will be set to either adStatusOk o r adStatusCantDeny. If it is set to
adStatusCantDeny, yo u c an’t set the parameter to adStatusCancel.

Table 14-16
Values for EventStatusEnum
Constant

Value

Description

AdStatusOK

1

The operation that triggered the event w as
successful.

adStatusErrorsOccured

2

The operation that triggered the event failed.

adStatusCantDeny

3

The operation can’t be canceled.

adStatusCancel

4

Requests that the operation that triggered
the event be canceled.

adStatusUnwantedEvent

5

Prevents subsequent notifications before the
event m ethod has finished executing.

pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Event FetchComplete (pError As Error, adStatus As EventStatusEnum,
pRecordset As Recordset)
The FetchComplete event is triggered after all o f the ro ws have been retrieved during an async hro no us o peratio n.

pError is an o bjec t referenc e to an Error o bjec t c o ntaining any erro r info rmatio n.
This pro perty is o nly valid if adStatus is set to adStatusErrorsOccured.
adStatus is an enumerated value that indic ates the ac tio n that sho uld be
taken when the event returns (see Table 14-16). Yo u may also set this value to
adStatusUnwantedEvent befo re the event c o mpletes to prevent it fro m being
c alled again.
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Event FetchProgress (Progress As Long, M axProgress As Long,
adStatus As EventStatusEnum, pRecordset As Recordset)
The FetchProgress event is fired perio dic ally during an async hro no us o peratio n
to repo rt ho w many ro ws have been retrieved.

Chapter 14 ✦ Working with Recordsets —Part I

Progress is a Long value indic ating the number o f rec o rds that have been
retrieved so far.
MaxProgress is a Long value indic ating the number o f rec o rds that are expec ted to
be retrieved.
adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16).
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Event FieldChangeComplete (cFields As Long, Fields, pError asError,
adStatus As EventStatusEnum, pRecordset As Recordset)
The FieldChangeComplete event is c alled after the values o f o ne o r mo re Field
o bjec ts have been c hanged. This c an happen if the pro gram assigns a value to the
Value pro perty o f the Field o bjec t o r by using the Update metho d and spec ifying
a list o f fields and values.

cFields is a Long value indic ating the number o f fields in Fields.
Fields is an array o f o bjec t po inters that po int to Field o bjec ts that were
c hanged.
pError is an Error o bjec t c o ntaining any erro r that may have o c c urred. This value
is valid o nly if adStatus is set to adStatusErrorsOccured.
adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16).
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Event M oveComplete (adReason As EventReasonEnum, pError As Error,
adStatus As EventStatusEnum, pRecordset as Recordset)
The MoveComplete event is c alled after the c urrent rec o rd has c hanged to a new
po sitio n in the Recordset.
Tip

Counting rows: If you w ant to display the relative position of the cursor in the

Recordset, the MoveComplete event is an ideal place for this. You can easily
use the AbsolutePosition property to display the current record num ber and
the RecordCount properties to display the total num ber of records retrieved.
adReason is an enumerated data type indic ating the o peratio n that o riginally
c aused the mo ve (see Table 14-17).

285

286

Part III ✦ Hardcore ADO

Table 14-17
Values for EventReasonEnum
Constant

Value

Description

adRsnAddNew

1

The operation executed an AddNew m ethod.

adRsnDelete

2

The operation used the Delete m ethod.

adRsnUpdate

3

The operation perform ed an Update m ethod.

adRsnUndoUpdate

4

The operation reversed an Update m ethod.

adRsnUndoAddNew

5

The operation reversed an AddNew m ethod.

adRsnUndoDelete

6

The operation reversed a Delete m ethod.

adRsnRequery

7

The operation perform ed a Requery.

adRsnResync

8

The operation perform ed a Resync.

adRsnClose

9

The operation closed the Recordset.

adRsnMove

10

The operation m oved the current record pointer
to a different record.

adRsnFirstChange

11

The operation m ade the first change to a row.

adRsnMoveFirst

12

The operation m oved the current record pointer
to the first record in the Recordset.

adRsnMoveNext

13

The operation m oved the current record pointer
to the next record in the Recordset.

adRsnMovePrevious

14

The operation m oved the current record pointer
to the previous record in the Recordset.

adRsnMoveLast

15

The operation m oved the current record pointer
to the last record in the Recordset.

pError is an Error o bjec t c o ntaining any erro r that may have o c c urred. This value
is o nly valid if adStatus is set to adStatusErrorsOccured.
adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16).
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Chapter 14 ✦ Working with Recordsets —Part I

Event RecordChangeComplete (adReason As EventReasonEnum,
cRecords As Long, pError As Error, adStatus As EventStatusEnum,
pRecordset as Recordset)
The RecordChangeComplete event is c alled after o ne o r mo re rec o rds in the
Recordset have been c hanged.

adReason is an enumerated data type indic ating the o peratio n that o riginally
c aused the c hange ( see Table 14-17) . Po ssible values are the fo llo wing:
adRsnAddNew, adRsnDelete, adRsnUpdate, adRsnUndoUpdate,
adRsnUndoAddNew, adRsnUndoDelete, and adRsnFirstChange.
cRecords is a Long value c o ntaining the number o f rec o rds that were c hanged.
pError is an Error o bjec t c o ntaining any erro r that may have o c c urred. This value
is o nly valid if adStatus is set to adStatusErrorsOccured.
adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16).
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Event RecordsetChangeComplete (adReason As EventReasonEnum,
pError As Error, adStatus As EventStatusEnum, pRecordset as
Recordset)
The RecordsetChangeComplete event is c alled after a c hange to the Recordset.

adReason is an enumerated data type indic ating the o peratio n that o riginally
c aused the mo ve (see Table 14-17). Po ssible values are the fo llo wing: adRsnClose,
adRsnReQuery, and adRsnReSync.
pError is an Error o bjec t c o ntaining any erro r that may have o c c urred. This value
is o nly valid if adStatus is set to adStatusErrorsOccured.
adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16).
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

287

288

Part III ✦ Hardcore ADO

Event WillChangeField (cFields As Long, Fields, adStatus As
EventStatusEnum, pRecordset As Recordset)
The WillChangeField event is c alled befo re an o peratio n that will c hange the values in o ne o r mo re Field o bjec ts is started. After the c hanges have been made, the
FieldChangeComplete event is fired. Yo u c an c ho o se to c anc el the o peratio n by
setting the adStatus pro perty to adStatusCancel.

cFields is a Long value indic ating the number o f fields in Fields.
Fields is an array o f o bjec t po inters that po int to Field o bjec ts that are to be
c hanged.
adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16).
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Event WillChangeRecord (adReason As EventReasonEnum, cRecords As
Long, pError As Error, adStatus As EventStatusEnum, pRecordset as
Recordset)
The WillChangeRecord event is c alled befo re o ne o r mo re rec o rds in the
Recordset will be c hanged.

adReason is an enumerated data type indic ating the o peratio n that c aused the
c hange (see Table 14-17). Po ssible values are the fo llo wing: adRsnAddNew,
adRsnDelete, adRsnUpdate, adRsnUndoUpdate, adRsnUndoAddNew,
adRsnUndoDelete, and adRsnFirstChange.
cRecords is a Long value c o ntaining the number o f rec o rds will be c hanged.
adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16).
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Event WillChangeRecordset (adReason As EventReasonEnum, pError As
Error, adStatus As EventStatusEnum, pRecordset as Recordset)
The WillChangeRecordset event is c alled befo re the Recordset is c hanged.

adReason is an enumerated data type indic ating the o peratio n that c aused the
c hange (see Table 14-17). Po ssible values are the fo llo wing: adRsnClose,
adRsnReQuery, and adRsnReSync.

Chapter 14 ✦ Working with Recordsets —Part I

pError is an Error o bjec t c o ntaining any erro r that may have o c c urred. This value
is o nly valid if adStatus is set to adStatusErrorsOccured.
adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16).
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Event WillM ove (adReason As EventReasonEnum, adStatus As
EventStatusEnum, pRecordset as Recordset)
The WillMove event is c alled befo re the c urrent rec o rd po inter is c hanged to a new
po sitio n in the Recordset.

adReason is an enumerated data type indic ating the o peratio n that o riginally
c aused the mo ve (see Table 14-16).
adStatus is an enumerated value that indic ates the ac tio n that sho uld be taken
when the event returns (see Table 14-16).
pRecordset is an o bjec t referenc e to the Recordset that triggered the event.

Before Opening a Recordset
Befo re yo u o pen a rec o rdset there are a number o f issues yo u need to c o nsider. Fo r
instanc e, yo u need to dec ide whether o r no t yo u plan to update the database. Then
yo u need to dec ide what type o f c urso r yo u want to use. Finally, yo u need to dec ide
where the c urso r sho uld be lo c ated. These issues have a big impac t o n ho w yo ur
applic atio n perfo rms, no t o nly fo r a single user, but fo r all o f the users that ac c ess
yo ur database server.

Locking considerations
One o f the pro blems o f running an applic atio n where multiple users are ac c essing
the same c o llec tio n o f info rmatio n is c o ntro lling ac c ess to the info rmatio n so that
two peo ple aren’t trying to update the same info rmatio n at the same time.
To understand why lo c king is impo rtant c o nsider the fo llo wing example. Assume
that yo ur bank runs two pro grams to update their ac c o unts at the same time (see
Figure 14-1). One pro gram applies depo sits, while the o ther applies withdrawals.
As luc k wo uld have it, bo th pro grams attempt to update yo ur ac c o unt at the same
time. Witho ut lo c king, the withdrawal pro gram may read the c urrent balanc e in

289

290

Part III ✦ Hardcore ADO

yo ur ac c o unt and begin to pro c ess the withdrawal. Then the depo sit pro gram reads
the c urrent balanc e and updates the database with the new balanc e. Finally, the
withdrawal pro gram po sts the balanc e it c o mputes. This is a serio us pro blem
(altho ugh I wish it wo rked the o ther way).

Without Locking
Withdraw al
Program

Apply W ithdraw al
of $700

Read Account
Balance

Deposit
Program

Apply Deposit
of $5000

Read Account
Balance

Time

Account
Balance
$1,426.55

$1,426.55

$6,426.55

$726.55

Figure 14-1: Processing concurrent database updates w ithout locks

To avo id this pro blem, yo u need to prevent all o ther users fro m ac c essing this partic ular ac c o unt until after the update has been c o mpleted. Figure 14-2 sho ws ho w the
same sequenc e o f ac tio ns wo uld wo rk with lo c ks. The withdrawal pro gram is able to
read the ac c o unt balanc e immediately, and it plac es a lo c k o n the ac c o unt so no
o ther pro grams c an ac c ess the info rmatio n. When the depo sit pro gram attempts to
read the balanc e, it is fo rc ed to wait fo r the lo c k to be released. This allo ws the withdrawal pro gram to finish its pro c essing uninterrupted and release the lo c k it plac ed
o n the ac c o unt. Onc e the lo c k is released, the ac c o unt balanc e will be returned to the
depo sit pro gram, whic h c an then c o mplete its updates ac c urately.

With Locking
With- Read Account
draw al
Balance
Program
W ith Lock
Deposit
Read Account
Program
Balance

Apply
W ithdraw al
of $700

Release Lock

Wait for Lock to be Released Apply Deposit
of $5000

Release Lock

Time

Account
Balance
$1,426.55

$1,426.55

$726.55

$726.55

$5,726.55

Figure 14-2: Processing concurrent database updates w ith locks

$5,726.55

Chapter 14 ✦ Working with Recordsets —Part I

As yo u c an see, lo c king is nec essary to ensure that c hanges to the database are
applied in the c o rrec t o rder. In mo st c ases, the o rder o f the c hanges against the
database isn’t impo rtant as lo ng as the c hanges are made sequentially rather than
c o nc urrently. After all, it do esn’t matter whether the depo sit is made first o r the
withdrawal is made first as lo ng as they aren’t made at the same time.
The ADO LockType allo ws yo u to c ho o se fro m o ne o f fo ur different types o f lo c ks:
read-o nly, pessimistic , o ptimistic , and batc h o ptimistic . Yo u need to c ho o se the o ne
that best suits yo ur needs.

Read-only locks
While lo c ks are nec essary when perfo rming updates, it is useful to tell the database
server that yo u are never go ing to update the data in the database. In a sense, a
re ad-o nly lo ck is no t a lo c k at all, but spec ifying a read-o nly lo c k ensures that yo u
c an’t update the database.

Pessimistic locks
A pe ssimistic lo ck is the mo st c o nservative lo c k available in ADO. When yo u begin
to edit a rec o rd by assigning a new value into o ne o f the existing fields in the ro w, a
lo c k is plac ed o n the ro w so that no o ther users c an ac c ess it. The ro w remains
lo c ked until yo u update it using the Update metho d.
One pro blem with using pessimistic lo c king is that in additio n to the ro w yo u are
mo difying, all o f the ro ws sto red in the same physic al blo c k o f sto rage (typic ally
c alled a database page ) are also lo c ked, whic h makes them unavailable fo r o ther
users also .
Note

In days of old: The current version of m ost popular database system s supports
row -level locking, w hich m eans that a lock affects only the row that it w as
intended for and not the other row s in the sam e physical block of storage.

Ho wever, a bigger pro blem with pessimistic lo c king is that the lo c k is held during
the entire time yo u are editing the ro w. Depending o n ho w yo ur applic atio n wo rks,
the lo c k c o uld be held any