Welcome to ADO

Microsoft® ActiveX® Data Objects (ADO) enable your client applications to access and manipulate data in a database server through any OLE DB provider.

For information about support for Microsoft data access components, see the Getting Help from Microsoft Technical Support page.

For information about the Data Access SDK, see the "Data Access SDK Overview.

© 1998 Microsoft Corporation. All rights reserved.

ADO Programmer's Reference

ADO supports key features for building client/server and Web-based applications. Its primary benefits are ease of use, high speed, low memory overhead, and a small disk footprint.

To learn more about ADO, see the ADO Overview. Please see the Microsoft Web page for ADO 2.0 Release Notes at http://www.microsoft.com/data/ado.

ADO MD Programmer's Reference

ADO MD extends ADO to include objects specific to multidimensional data, and allows you to browse multidimensional schema, query a cube, and retrieve the results.

To learn more about ADO MD, see the ADO MD Overview. Please see the Microsoft Web page for ADO MD Release Notes at http://www.microsoft.com/data/ado.


ADO Overview

Microsoft® ActiveX® Data Objects (ADO) enable your client applications to access and manipulate data in a database server through any OLE DB provider.

ADO enables you to write an application to access and manipulate data in a database server through an OLE DB provider. ADO's primary benefits are ease of use, high speed, low memory overhead, and a small disk footprint. ADO supports key features for building client/server and Web-based applications.

ADO also features Remote Data Service (RDS), by which you can move data from a server to a client application or Web page, manipulate the data on the client, and return updates to the server in a single round trip. Previously released as Microsoft Remote Data Service 1.5, RDS has been combined with the ADO programming model to simplify client-side data remoting.

For more information about ADO and how RDS integrates with it, see Getting Started with ADO.


Shorthand for Creating a Recordset

ADO provides a new shorthand method to create a Recordset by appending new Field objects to the Fields collection of a Recordset. Later, you can open the Recordset and insert data from any source—not necessarily a database—into it. You can also manufacture the data programmatically.

The new Recordset can employ all the data manipulation methods available to any Recordset. Use the Recordset to supply information to a visual control, or even to update an actual data source.


Recordset Persistence

With recordset persistence, you can save Recordset data and metadata as a file. Later, use the persisted file to re-create the Recordset object. The persisted file may exist on a local drive, network server, or as a URL on a Web site.

In addition, the new GetString method converts a Recordset object to a form in which the columns and rows are delimited with characters you specify.

Details

The MSPersist provider supports storing a Recordset object in a file with the Recordset object Save method. Later, the persisted file can be restored with either the Recordset object Open, or Connection object Execute methods.

The Recordset object is converted to a string so it can be stored in a file. Currently, the only supported string format is the Microsoft proprietary Advanced Data TableGram (ADTG) format. The MSPersist provider adds a string-valued property, named PersistFormat, to the Recordset object's Properties collection so you can get or set the string format. The default value of PersistFormat is adPersistADTG.

Pending changes are saved in the persisted file. Therefore, you can issue a query that returns a Recordset object; edit the recordset; save it and the pending changes; later, restore the recordset; then update the data source with the saved pending changes.

Usage

Get the current string format:

Dim strFormat as String
strFormat = rs.Properties("PersistFormat")

Save a Recordset:

Dim rs as New ADODB.Recordset
rs.Save "c:\yourFile.adtg", adPersistADTG

Open a persisted file with Recordset.Open:

dim rs as New ADODB.Recordset
rs.Open "c:\yourFile.adtg", "Provider=MSPersist",,,adCommandFile

Optionally, if the Recordset does not have an active connection, you can accept all the defaults and simply code:

dim rs as New ADODB.Recordset
rs.Open "c:\yourFile.adtg"

Open a persisted file with Connection.Execute:

dim conn as New ADODB.Connection
dim rs as New ADODB.Recordset
conn.Open "Provider=MSPersist"
set rs = conn.execute("c:\yourFile.adtg")

Open a persisted file with RDS.DataControl:

In this case, the Server property is not set.

Dim dc as New RDS.DataControl
dc.Connection = "Provider=MSPersist"
dc.SQL = "c:\yourFile.adtg"
dc.Refresh


Index Support and Find, Sort, and Filter

Indexes on fields can greatly enhance the performance of the new Recordset object Find method, and Sort and Filter properties. In ADO 2.0, you can create an internal index for a Field object by setting its dynamic Optimize property. This dynamic property is added to the Field object’s Properties collection when you set the CursorLocation property to adUseClient. Remember that this index is internal to ADO 2.0—you can't gain access to it or use it for any other purpose.

The Sort property determines the order in which rows of a Recordset are traversed; the Filter property determines which rows are accessible when traversing rows; and the Find method quickly locates a value within an indexed column (field) of a Recordset.


ADO for Windows Foundation Classes

You can now access data using the ADO application programming interface with Microsoft® Visual J++™ (the Java programming language).

ADO for Windows Foundation Classes (ADO/WFC) supports all the standard ADO methods, properties, objects, and events. However, operations that require a VARIANT as a parameter and show excellent performance in a language like Microsoft® Visual Basic®, display lesser performance in a language like Visual J++. For that reason, ADO/WFC also provides accessor functions on the Field object that take native Java data types instead of the VARIANT data type.

This feature will be available with the release of Visual J++ version 6.


ADO Event Model and Asynchronous Operations

The ADO Event Model supports certain synchronous and asynchronous ADO operations that issue events before the operation starts or after it completes. An event is actually a call to an event handler routine.

Event handlers that are called before the operation starts allow you to examine or modify the operation parameters, then either cancel the operation or allow it to complete.

Event handlers that are called after an operation completes are especially important now that ADO 2.0 supports asynchronous operations. For example, an application that starts an asynchronous Recordset.Open operation is notified by an execution complete event when the operation concludes.

There are two families of events:

  • ConnectionEvents—Events are issued when a transaction on a connection begins, is committed, or is rolled back; when a Command executes; and when a Connection starts or ends.

  • RecordsetEvents—Events are issued when you navigate through the rows of a Recordset object; change a field in a row of a Recordset; change a row in a Recordset; or make any change whatsoever in the Recordset.


ADO Event Summary

  • ADO 2.0 supports events, which are notifications that certain operations are about to occur or have occurred.

  • There are two families of events: ConnectionEvent and RecordsetEvent. The Connection object issues ConnectionEvent events, and the Recordset object issues RecordsetEvent events.

  • Events are processed by event handler routines, which are called before certain operations start or after such operations conclude.

  • Some events are paired. Events called before an operation starts have names of the form WillEvent (Will events) and events called after an operation concludes have names of the form EventComplete (Complete events).

  • The remaining, unpaired events occur only after an operation concludes. (Their names are not formed in any particular pattern.)

  • The event handlers are controlled by the status parameter. Additional information is provided by the error and object parameters.

  • You can request an event handler not to receive any more notifications after the first notification. For example, you could choose to receive only Will events or Complete events.

  • In certain programming languages, events from multiple ADO objects can be processed by one event handler. And although less common, one event can be processed by multiple event handlers.


ADO Events

ADO 2.0 supports events. An event is a notification issued by certain operations before the operation starts or after it completes. An event is actually a call to an event handler routine that you define in your application. See ADO Event Instantiation by Language.

There are two families of events. The ConnectionEvent family pertains to operations on the Connection object, and the RecordsetEvent family pertains to operations on the Recordset object.

  • ConnectionEvents—Events are issued when a transaction on a connection begins, is committed, or is rolled back, when a Command executes, and when a Connection starts or ends.

  • RecordsetEvents—Events are issued when you navigate through the rows of a Recordset object, change a field in a row of a Recordset, change a row in a Recordset, or make any change whatsoever in the Recordset.

ADO Event Handler Summary

ConnectionEvent | Description
BeginTransComplete, CommitTransComplete, RollbackTransComplete | Transaction Management—Notification that the current transaction on the connection has started, committed, or rolled back.
WillConnect, ConnectComplete, Disconnect | Connection Management—Notification that the current connection will start, has started, or has ended.
WillExecute, ExecuteComplete | Command Execution Management—Notification that the execution of the current command on the connection will start, or has ended.
InfoMessage | Informational—Notification that there is additional information about the current operation.

RecordsetEvent | Description
FetchProgress, FetchComplete | Retrieval Status—Notification of the progress of a data retrieval operation, or that the retrieval operation has completed.
WillChangeField, FieldChangeComplete | Field Change Management—Notification that the value of the current field will change, or has changed.
WillMove, MoveComplete , EndOfRecordset | Navigation Management—Notification that the current row position in a Recordset will change, has changed, or has reached the end of the Recordset.
WillChangeRecord, RecordChangeComplete | Row Change Management—Notification that something in the current row of the Recordset will change, or has changed.
WillChangeRecordset, RecordsetChangeComplete | Recordset Change Management—Notification that something in the current Recordset will change, or has changed.


Types of Events

Will Events

Event handlers called before the operation starts offer you the opportunity to examine or modify the operation parameters, then either cancel the operation or allow it to complete. These event handler routines usually have names of the form WillEvent (Will events).

Complete Events

Event handlers called after an operation completes can notify your application that an operation has concluded. Such an event handler is also notified when a pending operation is canceled by a Will event handler. These event handler routines usually have names of the form EventComplete (Complete events).

Will and Complete events are typically used in pairs.

The Other Events

The other event handlers—that is, events whose names are not of the form WillEvent or EventComplete—are called only after an operation completes.


Event Parameters

Every event handler has a status parameter that controls the event handler. Most Complete events have an error parameter to report whether the operation causing the event succeeded, and an object parameter to identify the ADO object to which the operation applied.

Will events are also passed the parameters to be used in the pending operation. This gives you the opportunity to examine the parameters and determine whether the operation should complete or not.

Status Parameter

When the event handler routine is called, the status parameter is set to one of the following informational values.

Value | Description
adStatusOK | The operation that caused the event occurred successfully.
adStatusErrorsOccurred | The operation that caused the event occurred unsuccessfully, or a Will event canceled the operation. Check the error parameter for more details.
adStatusCantDeny | A Will event cannot request cancellation of the operation about to occur.

Before the event handler routine returns, leave the status parameter unchanged or set it to one of the following request values.

Value | Description
adStatusUnwantedEvent | Request this event handler receive no further notifications.
adStatusCancel | Request cancellation of the operation that is about to occur.

Depending on event type, the status operand can have one of the following values when the event handler is called.

Event Type | Value
Will | adStatusOK, adStatusCantDeny
Complete | adStatusOK, adStatusErrorsOccurred

Depending on event type, the status operand can have one of the following values when the event handler returns.

Event Type | Value
Will | adStatusOK, adStatusCancel, adStatusUnwantedEvent
Complete | adStatusOK, adStatusUnwantedEvent

Error Parameter

The error parameter is a reference to an ADO Error object containing details about why the operation failed if the status parameter equals adStatusErrorsOccurred.

Object Parameter

The object parameter is a reference to the ADO object for which the operation applies. For example, you could have several Connection objects open at one time and only one Disconnect event handler. If any one connection closed, the Disconnect event handler would be called with the object parameter set to the Connection object that closed.

Reason Parameter

Some event handlers have an adReason parameter, which provides additional information about why the event occurred. Methods with an adReason parameter may be called several times—even for the same operation, but for a different reason each time.

For example, the WillChangeRecord event handler is called for operations that are about to do or undo the insertion, deletion, or modification of a record. Use the adReason parameter as a filter to only process particular events.

You must return adStatusUnwantedEvent in the adStatus parameter to request that an event handler without an adReason parameter stop receiving event notifications. However, an event handler with an adReason parameter may receive several notifications, each for a different reason. Therefore, you must return adStatusUnwantedEvent for each notification caused by a different reason.

For example, assume you have a WillChangeRecord event handler coded in Microsoft® Visual Basic®. If you don't want to receive any further notifications whatsoever, simply code the following:

Set adStatus = adStatusUnwantedEvent

However, if you want to process events where the row is about to be deleted, but cancel notifications for all other reasons, then code the following:

if (adReason = adRsnDelete)
' Process an event for this reason.
...
else
' Stop receiving events for any other reason.
Set adStatus = adStatusUnwantedEvent
...


How Event Handlers Work Together

All the event handlers in the ConnectionEvent and RecordsetEvent families must be implemented, regardless of whether you actually use events. The amount of implementation work you have to do depends on your programming language. Some languages, like Microsoft Visual Basic, do all the work for you. Other languages, like Microsoft® Visual C++®, require you to do all the work. Microsoft® Visual J++™ with ADO/WFC takes the middle road and does much of the work for you. For more information, see ADO Event Instantiation by Language.

Although implementing the event handler yourself is more work, you can also do things that languages such as Visual Basic won't allow. For example, in Microsoft Visual C++ one RecordsetEvent handler can process notifications from operations on multiple Recordset objects.

Will and Complete event handlers can be used in pairs or separately.

Paired Event Handlers

  • First, let's examine what happens when a Will event succeeds.

    Imagine paired WillChangeField and FieldChangeComplete events for a Recordset object. In your application, you start to change the value of a field. The WillChangeField event handler is called. You return an indication that it's acceptable to change the field. The operation completes and a FieldChangeComplete event notifies your application that the operation has ended. The event handler status operand reports the success of the operation.

  • Next, let's examine what happens when a Will event cancels an operation.

    Imagine that you change another field. The WillChangeField event handler is called. You decide for some reason that it is not acceptable to change the field, so you return adStatusCancel in the status operand. As a result, the operation does not complete.

    The FieldChangeComplete event notifies you that the operation has ended. The event handler status operand is set to adStatusErrorsOccurred; the error parameter refers to an Error object; and the Error object Number property is set to either an ADO or provider value indicating the operation is canceled.

  • More than one Will and Complete event handler can be called for the same operation. Let's examine what happens when multiple Will events succeed.

    Imagine paired WillChangeField, FieldChangeComplete, WillChangeRecord and RecordChangeComplete events for a Recordset object. You start to change the value of a field; the WillChangeField event handler is called, and you return an indication that it's acceptable to change the field.

    Next, the WillChangeRecord event handler is called, and once again you indicate that the operation should complete.

    Note In general, all the Will event handlers pertaining to a particular instance of an ADO object will be called. However, they will be called in no particular order.

    When the operation completes, the FieldChangeComplete and RecordChangeComplete event handlers are called.

  • More than one Will and Complete event handler can be called for the same operation, but one may cancel the pending operation. Let's examine what happens when the last of multiple Will events cancels an operation.

    Once again, imagine paired WillChangeField, FieldChangeComplete, WillChangeRecord and RecordChangeComplete events. You start to change the value of a field; the WillChangeField event handler is called, and you return an indication that it's acceptable to change the field.

    Next, the WillChangeRecord event handler is called. Perhaps you determine the field change is alright in itself, but it will create an error in the record as a whole. You return adStatusCancel to indicate it is not acceptable to change the field. The WillChangeField event handler has already allowed the operation.

    The operation does not complete because it was canceled by the WillChangeRecord event handler. The FieldChangeComplete event handler is called with the status operand set to adStatusErrorsOccurred; the error parameter is set appropriately.

    Next, the RecordChangeComplete event handler is also called with the status operand set to adStatusErrorsOccurred. The matching Complete event is called for the Will event.

  • More than one Will and Complete event handler can be called for the same operation, but one may cancel the pending operation. Let's examine what happens when an event handler other than the last of multiple Will events cancels an operation.

    Once again, imagine the same set of paired event handlers as before. You start to change the value of a field; the WillChangeField event handler is called, and you return adStatusCancel to indicate it is not acceptable to change the field. The operation does not complete; the FieldChangeComplete event notifies you that the operation has ended with the status and error parameters set appropriately.

    However, the WillChangeRecord (and thus the RecordChangeComplete) event handler is not called because the first Will event canceled the operation. In general, if a Will event cancels an operation, no remaining Will event handler will be called.

Unpaired Event Handlers

You can turn off event notifications for any event by returning adStatusUnwantedEvent in the status parameter. For example, when your first Complete event handler is called, return adStatusUnwantedEvent and you will subsequently receive only Will events.

Single Will event handlers can be useful when you want to examine the parameters that will be used in an operation. You can modify those operation parameters or cancel the operation.

Alternatively, leave Complete event notification turned on, and when your first Will event handler is called, return adStatusUnwantedEvent. You will subsequently receive only Complete events.

Single Complete event handlers can be useful for managing asynchronous operations. Each asynchronous operation has an appropriate Complete event.

For example, it can take a long time to populate a very large Recordset object. If your application is appropriately written, you can start a Recordset.Open(...,adAsyncExecute) operation and continue with other processing. You will eventually be notified when the Recordset is populated by an ExecuteComplete event.

Single Event Handlers and Multiple Objects

The flexibility of a programming language like Microsoft Visual C++ enables you to have one event handler process events from multiple objects. For example, you could have one Disconnect event handler process events from several Connection objects. If one of the connections ended, the Disconnect event handler would be called. You could tell which connection caused the event because the event handler object parameter would be set to the corresponding Connection object.

This technique cannot be used in Visual Basic because that language can correlate only one object to an event.

Multiple Event Handlers and Single Operations

It is possible, though less useful, to associate one ADO object and its operations to multiple sets of events. For example, you could create multiple WillChangeField events to each perform a particular field validation edit. If a field were about to change, one Will event could validate some aspect of the field value, then another Will event could validate a different aspect.

The reason why this isn't a very useful technique is that you could simply perform or call all your edits from a single event handler. However, we mention the idea for the sake of completeness.


ADO Events in ADO/WFC

  • ADO for Windows Foundation Classes (ADO/WFC) builds on the ADO Event Model and presents a simplified application programming interface.

  • In general, ADO/WFC intercepts ADO events, consolidates the event parameters into a single event class, then calls your event handler.

To use ADO Events in ADO/WFC

  1. Define your own event handler method to process an event. For example, if you wanted to process the ConnectComplete event in the ConnectionEvent family, you might use this code:
    public void onConnectComplete(Object sender,ConnectionEvent e)
{
System.out.println("onConnectComplete:" + e);
}
  2. Define a handler object to represent your event handler method. The handler object should be of data type ConnectEventHandler for an event of type ConnectionEvent, or data type RecordsetEventHandler for an event of type RecordsetEvent. For example, code the following for your ConnectComplete event handler:
    ConnectionEventHandler handler =
new ConnectionEventHandler(this, "onConnectComplete");

    The first argument of the ConnectionEventHandler constructor is a reference to the class that contains the method named in the second argument.

    The Microsoft Visual J++ compiler also supports an equivalent syntax:

    ConnectionEventHandler handler =
new ConnectionEventHandler(this.onConnectComplete);

    The single argument is a reference to the desired class (that is, this) and method within the class (that is, onConnectComplete).

  3. Add your event handler to a list of handlers designated to process a particular type of event. Use the method with a name such as addOn EventName(handler).

  4. ADO/WFC internally implements all the ADO Event handlers. Therefore, an event caused by a Connection or Recordset operation is intercepted by an ADO/WFC event handler.

    The ADO/WFC event handler passes ADO ConnectionEvent parameters in an instance of the ADO/WFC ConnectionEvent class, or ADO RecordsetEvent parameters in an instance of the ADO/WFC RecordsetEvent class. These ADO/WFC classes consolidate the ADO event parameters; that is, each ADO/WFC class contains one data member for each unique parameter in all the ADO ConnectionEvent or RecordsetEvent methods.

  5. ADO/WFC then calls your event handler with the ADO/WFC event object. For example, your onConnectComplete handler has a signature like this:
    public void onConnectComplete(Object sender,ConnectionEvent e)

The first argument is the type of object that sent the event (Connection or Recordset), and the second argument is the ADO/WFC event object (ConnectionEvent or RecordsetEvent).

The signature of your event handler is simpler than an ADO event. However, you must still understand the ADO Event model to know what parameters apply to an event and how to respond.

  6.
Return from your event handler to the ADO/WFC handler for the ADO Event. ADO/WFC copies pertinent ADO/WFC event data members back to the ADO event parameters, then the ADO Event handler returns.

    7.

  7.
When you are finished processing, remove your handler from the list of ADO/WFC event handlers. Use the method with a name such as removeOn EventName(handler).
    8.


ADO Event Instantiation by Language

Each programming language creates instances of ADO events differently. All the examples that follow create a ConnectComplete event handler.

Visual Basic

Dim WithEvent connEvent as Connection
Dim conn as New Connection
set connEvent = conn      'Turn on event support.
conn.Open(...)
...
set connEvent = Nothing   'Turn off event support.
...
Private Sub connEvent_ConnectComplete(ByVal err as ADODB.Error, adStatus as ADODB.EventStatus, ByVal pConnectionas ADODB.Connection)
'Check the error object only if adStatus equals adStatusErrorsOccurred.
...
End Sub

Visual C++

This is a schematic description of how to instantiate ADO events in VC++.

Create classes derived from the ConnectionEventsVt and RecordsetEventsVt interfaces found in file adoint.h.

class CConnEvent : public ConnectionEventsVt
{
   public:
   STDMETHODIMP InfoMessage(
            ADOError *pError,
            EventStatusEnum *adStatus,
           _ADOConnection *pConnection);
...
}

class CRstEvent : public RecordsetEventsVt
{
    public:
       STDMETHODIMP WillChangeField(
             LONG cFields,
             VARIANT Fields,
             EventStatusEnum *adStatus,
             _ADORecordset *pRecordset);
...
}

Implement each of the event handler methods in both classes. It's sufficient that each method merely return an HRESULT of S_OK. However, when you make it known that your event handlers are available, they will be called continuously by default. Instead, you may want to request no further notification after the first time by setting adStatus to adStatusUnwantedEvent.

STDMETHODIMP CConnEvent::ConnectComplete(
             ADOError *pError,
             EventStatusEnum *adStatus,
             _ADOConnection *pConnection)
      {
      *adStatus = adStatusUnwantedEvent;
      return S_OK;
      }

The event classes inherit from IUnknown, so you must also implement the QueryInterface, AddRef and Release methods. Also implement class constructors and destructors. Choose the VC++ tools with which you are most comfortable that will simplify this part of the task.

Make it known that your event handlers are available by issuing QueryInterface on the Recordset and Connection objects for the IConnectionPointContainer and IConnectionPoint interfaces. Then issue IConnectionPoint::Advise for each class.

For example, assume you're in a Boolean function that returns True if it successfully informs a Recordset object that you have event handlers available.

HRESULT   hr;
DWORD      dwEvtClass;
IConnectionPointContainer   *pCPC = NULL;
IConnectionPoint            *pCP = NULL;
CRstEvent                  *pRStEvent = NULL;
...
_RecordsetPtr    pRs();
pRs.CreateInstance(__uuidof(Recordset));
pRStEvent = New CRstEvent();
if (pRStEvent == NULL) return FALSE;
...
hr = pRs->QueryInterface(IID_IConnectionPointContainer, &pCPC);
if (FAILED(hr)) return FALSE;
hr = pCPC->FindConnectionPoint(IID_ADORecordsetEvents, &pCP);
pCPC->Release();   // Always Release now, even before checking.
if (FAILED(hr)) return FALSE;
hr = pCP->Advise(pRstEvent, &dwEvtClass);   //Turn on event support.
pCP->Release();
if (FAILED(hr)) return FALSE;
...
return TRUE;
...

At this point, events for the RecordsetEvent family are turned on and your methods will be called as Recordset events occur.

Later, when you want to make your event handlers unavailable, get the connection point again and issue the IConnectionPoint::UnAdvise method.

...
hr = pCP->UnAdvise(dwEvtClass);   //Turn off event support.
pCP->Release();
if (FAILED(hr)) return FALSE;
...

Of course, you must release interfaces and destroy class objects as appropriate .

Visual J++

import wfc.data.*;
public class MyClass
{
ConnectionEventHandler handler =
   new ConnectionEventHandler(this,"onConnectComplete");

public void onConnectComplete(Object sender,ConnectionEvent e)
{
   if (e.adStatus == AdoEnums.EventStatus.ERRORSOCCURRED)
      System.out.println("Connection failed");
   else
      System.out.println("Connection completed");
   return;
}

void main( void )
{
   Connection conn = new Connection();

   conn.addOnConnectComplete(handler);      // Turn on event support.
   conn.open("DSN=pubs");
   conn.close();
   conn.removeOnConnectComplete(handler);   // Turn off event support.
}
}

VBScript

VBScript does not support events.


VC++ Extensions for ADO

One of the most tedious jobs Visual C++ programmers face when retrieving data with ADO is having to convert data returned as a VARIANT data type into a C++ data type, then storing the converted data in a class or structure. In addition to being cumbersome, retrieving C++ data through a VARIANT data type diminishes performance.

ADO 2.0 provides an interface that supports retrieving data into native C/C++ data types without going through a VARIANT, and also provides preprocessor macros that simplify using the interface. The result is a flexible tool that is easier to use and has great performance.


ADO VC++ Extensions Summary

  • ADO 2.0 provides an interface method and preprocessor macros to simplify converting the Recordset field values into C/C++ variables.

  • These extensions are simple to use and provide excellent performance.

  • A summary describes the supplied preprocessor macros and interface method.

  • A code example shows details of the VC++ Extensions header file.

  • Examples show how to convert field values with and without the ADO VC++ Extensions.


ADO VC++ Extensions

Programmers using Microsoft® Visual C++® to retrieve data with ADO must tediously convert data returned as a VARIANT data type into a C++ data type, then store the converted data in a class or structure. The process of retrieving C++ data through a VARIANT data type is cumbersome and diminishes performance.

Version 2.0 of ADO provides an interface that supports retrieving data into native C/C++ data types without going through a VARIANT. In addition, preprocessor macros that simplify using the interface are provided.

The result is a tool that is flexible, easier to use, and has great performance.

ADO Without Extensions

A common C/C++ client scenario is to bind a record in a Recordset to a C/C++ struct/class containing native C/C++ types. When going through VARIANTs, this involves writing conversion code from VARIANT to C/C++ native types. The ADO VC++ Extensions are targeted at making this scenario much easier for the VC++ programmer.

See Example: ADO Without Extensions as an example of how fetching data through VARIANTs is cumbersome in C or C++.


Using ADO VC++ Extensions

Define Binding Entries

The ADO VC++ Extensions map the fields of a Recordset object to C/C++ variables. The definition of a mapping between a field and a variable is called a binding entry. Preprocessor macros are provided to define binding entries for numeric, fixed-length, and variable-length variables.

Bracket your binding entries between BEGIN_ADO_BINDING and END_ADO_BINDING macros. You should not terminate your binding entries by either commas or semicolons. These delimiters are specified for you within the macros.

Specify one binding entry for each field to be converted to a C/C++ variable. Use the appropriate ADO_FIXED_LENGTH_BINDING_ENTRY, ADO_NUMERIC_BINDING_ENTRY, or ADO_VARIABLE_LENGTH_BINDING_ENTRY macros.

In the parameters for the macros, the Recordset field to be extracted is specified by an ordinal number—zero identifies the first field, one identifies the second field, and so on.

The C/C++ variable is declared with a data type. If the variable is numeric, you can also specify precision and scale. If the variable is variable-length, like a string, you must specify the maximum size of the variable in bytes. The Recordset field value will be coerced to this data type if necessary.

Specify a temporary work buffer, which will be used to convert the field value from a VARIANT to a C/C++ variable. The buffer should be at least as large as the C/C++ variable.

Set the Boolean modify parameter to TRUE to enable ADO to update the bound field, and FALSE if you merely want to examine the field but not change it. The VC++ Extension doesn't maintain state information about a field, so you must specify whether ADO should change a field's value (for example, the value of an autoincrement field maintained by the data source). Therefore, the modify parameter for such a field should be set to FALSE.

The status parameter tells you whether the conversion from a Recordset field to a C or C++ variable was successful and whether the contents of the variable are valid. The two most important values for this parameter are adFldOK, which means the conversion was successful; and adFldNull, which means the field was NULL—it had no value to convert.

Check this parameter first to determine if the C or C++ variable is valid. For example, if a field has valid contents for a row, status will be adFldOK. If you move to another row where the field is NULL, status will be adFldNull. However, the contents of the C or C++ variable will be unchanged—the variable will still contain the value of the field from the previous row.

Bind the Recordset to Variables

In your application, call the BindToRecordset interface method to associate (or bind) the Recordset fields to C/C++ variables. Your C/C++ variables will automatically be updated whenever the current row of the Recordset object changes.

Header Files

Include the following file in your application in order to use the VC++ Extensions:

  • #include <icrsint.h>

Interface Methods

The IADORecordBinding interface has methods to associate Recordset fields with C/C++ variables, add new rows, and perform updates. All three methods take a pointer to a class derived from CADORecordBinding, which defines the binding between each field and variable.

The interface methods are:

  • BindToRecordset(&binding)

Call this method to associate fields with variables.

  • AddNew(&binding)

Call this method to indirectly invoke the ADO AddNew method.

  • Update(&binding)

Call this method to indirectly invoke the ADO Update method.

Preprocessor macros

  • BEGIN_ADO_BINDING(cls)

  • ADO_FIXED_LENGTH_BINDING_ENTRY(Ordinal, DataType, Buffer, Status, Modify)

  • ADO_NUMERIC_BINDING_ENTRY(Ordinal, DataType, Buffer, Precision, Scale,
    Status, Modify)

  • ADO_VARIABLE_LENGTH_BINDING_ENTRY(Ordinal, DataType, Buffer, Size,
    Status, Modify)

  • END_ADO_BINDING()
Parameter | Description
cls | Class where the binding entries, buffer, and Recordset object are defined.
Ordinal | Ordinal field number; zero for the first field, one for the second, and so on.
DataType | Data type of the variable where the converted field will be stored.
Buffer | Buffer used to convert the field to a variable.
Status | Indicates the success of the field conversion.
Modify | A Boolean flag; if TRUE, indicates ADO can update the associated field.
Precision | Number of digits that can be represented in the numeric variable.
Scale | Number of decimal places in the numeric variable.
Size | Number of bytes required for a variable-length variable, such as a string.

status Parameter Values | Description
adFldOK | A non-NULL field value was returned.
adFldBadAccessor | Binding was invalid.
adFldCantConvertValue | Value couldn't be converted for reasons other than sign mismatch or data overflow.
adFldNull | A NULL was returned.
adFldTruncated | Variable-length data or numeric digits were truncated.
adFldSignMismatch | Value is signed and variable data type is unsigned.
adFldDataOverFlow | Value is larger than could be stored in the variable data type.
adFldCantCreate | Unknown column type and field already open.
adFldUnavailable | Field value could not be determined—for example, on a new, unassigned field with no default value.
adFldPermissionDenied | When updating, no permission to write data.
adFldIntegrityViolation | When updating, field value would violate column integrity.
adFldSchemaViolation | When updating, field value would violate column schema.
adFldBadStatus | When updating, invalid status parameter.
adFldDefault | When updating, a default value was used.


VC++ Extensions Header in Detail

The following header, icrsint.h, details the interfaces that allow clients to fetch a row of data directly into class data members. Clients need to include binding entries in their class to specify the association between a Recordset Field object and a class data member.

#ifndef _ICRSINT_H_
#define _ICRSINT_H_

#include <olectl.h>
#include <stddef.h>

// forwards
class CADORecordBinding;

#define classoffset(base, derived) \
   ((DWORD)(static_cast<base*>((derived*)8))-8)

enum FieldStatusEnum
{
   adFldOK = 0,
   adFldBadAccessor = 1,
   adFldCantConvertValue = 2,
   adFldNull = 3,
   adFldTruncated = 4,
   adFldSignMismatch = 5,
   adFldDataOverFlow = 6,
   adFldCantCreate = 7,
   adFldUnavailable = 8,
   adFldPermissionDenied = 9,
   adFldIntegrityViolation = 10,
   adFldSchemaViolation = 11,
   adFldBadStatus = 12,
   adFldDefault = 13
};

typedef struct stADO_BINDING_ENTRY
{
   ULONG         ulOrdinal;
    WORD         wDataType;
   BYTE         bPrecision;
   BYTE         bScale;
   ULONG         ulSize;
   ULONG         ulOffSet;
   ULONG         ulIADOBindingEntriesOffSet;
   ULONG         ulFldStatusOffset;
   BOOL         fModify;
} ADO_BINDING_ENTRY;

#define BEGIN_ADO_BINDING(cls) public: \
   typedef cls ADORowClass; \
   const ADO_BINDING_ENTRY* STDMETHODCALLTYPE GetADOBindingEntries() { \
   static const ADO_BINDING_ENTRY rgADOBindingEntries[] = {

#define ADO_FIXED_LENGTH_BINDING_ENTRY(Ordinal, DataType, Buffer, \   Status, Modify)\
   {Ordinal, \
   DataType, \
   0, \
   0, \
   0, \
   offsetof(ADORowClass, Buffer), \
   classoffset(CADORecordBinding, ADORowClass), \
   offsetof(ADORowClass, Status), \
   Modify},

#define ADO_NUMERIC_BINDING_ENTRY(Ordinal, DataType, \
   Buffer, Precision, Scale, Status, Modify)\
   {Ordinal, \
   DataType, \
   Precision, \
   Scale, \
   0, \
   offsetof(ADORowClass, Buffer), \
   classoffset(CADORecordBinding, ADORowClass), \
   offsetof(ADORowClass, Status), \
   Modify},

#define ADO_VARIABLE_LENGTH_BINDING_ENTRY(Ordinal, DataType, \
   Buffer, Size, Status, Modify)\
   {Ordinal, \
   DataType, \
   0, \
   0, \
   Size, \
   offsetof(ADORowClass, Buffer), \
   classoffset(CADORecordBinding, ADORowClass), \
   offsetof(ADORowClass, Status), \
   Modify},

#define END_ADO_BINDING() {0, adEmpty, 0, 0, 0, 0, 0, adFldOK, FALSE}};\
   return rgADOBindingEntries;}

//
// Interface that the client 'record' class needs to support.
// The ADO Binding entries provide the implementation for this interface.
//
class CADORecordBinding
{
public:
   STDMETHOD_(const ADO_BINDING_ENTRY*, GetADOBindingEntries)
   (VOID) PURE;
};

//
// Interface that allows a client to fetch a record of data into
// class data members.
//
DEFINE_GUID(IID_IADORecordBinding,
            0x00000544, 0, 0x10, 0x80,0,0,0xAA,0,0x6D,0x2E,0xA4);
DECLARE_INTERFACE_(IADORecordBinding, IUnknown)
{
public:
   STDMETHOD(BindToRecordset)(CADORecordBinding *pAdoRecordBinding)PURE;
   STDMETHOD(AddNew)(CADORecordBinding *pAdoRecordBinding) PURE;
   STDMETHOD(Update)(CADORecordBinding *pAdoRecordBinding) PURE;
};

#endif // !_ICRSINT_H_


Example: ADO Without Extensions

This program fragment shows how values are retrieved from fields and converted to C++ variables.

#import "c:\Program Files\Common Files\System\ADO\msado15.dll"
   no_namespace rename("EOF", "EndOfFile")
#include <stdio.h>

Class CEmployee
{
public:
   FetchEmployeeData();

   char m_szFirstName[30];
   char m_szLastName[30];
   int nAge;
};

CEmployee::FetchEmployeeData()
{
_ConnectionPtr   pCon();
_RecordsetPtr    pRs();
FieldPtr         pfldFirstName, pfldLastName, pfldAge;
_variant_t      vFirstName, vLastName, vAge;

pCon.CreateInstance(__uuidof(Connection));
pCon->Open(“pubs”, “sa”, “”);

pRs.CreateInstance(__uuidof(Recordset));
pRs->Open(“select FirstName, LastName, Age from Employees”, pCon,
   adOpenForwardOnly, adLockReadOnly, adCmdUnknown);

pfldFirstName = pRs->Fields->GetItem(0);
pfldLastName = pRs->Fields->GetItem(1);
pfldAge = pRs->Fields->GetItem(2);

while (VARIANT_FALSE == pRs->EndOfFile)
   {
   vFirstName.Clear();
   vLastName.Clear();
   vAge.Clear();

   vFirstName = pfldFirstName->Value;
   WideCharToMultiByte(CP_ACP, 0, vFirstName.bstrVal, -1,
      m_szFirstName, sizeof(m_szFirstName), NULL, NULL);

   vLastName = pfldLastName->Value;
   WideCharToMultiByte(CP_ACP, 0, vLastName.bstrVal, -1,
      m_szLastName, sizeof(m_szLastName), NULL, NULL);

   nAge = vAge.iVal;

   pRs->MoveNext();
   }
}


Example: ADO with Extensions

This program shows how values are retrieved from fields and converted to C++ variables. It includes the functionality described in the program fragment, Example: ADO Without Extensions.

#define INITGUID
#import "c:\Program Files\Common Files\System\ADO\msado15.dll"
   no_namespace rename("EOF", "EndOfFile")
#include <stdio.h>
#include "icrsint.h"

void dump_com_error(_com_error &e)
   {
printf("Error\n");
printf("\a\tCode = %08lx\n", e.Error());
printf("\a\tCode meaning = %s", e.ErrorMessage());
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
printf("\a\tSource = %s\n", (LPCSTR) bstrSource);
printf("\a\tDescription = %s\n", (LPCSTR) bstrDescription);
   }

class CCustomRs :
   public CADORecordBinding
{
BEGIN_ADO_BINDING(CCustomRs)
   ADO_VARIABLE_LENGTH_BINDING_ENTRY(1, adVarChar, m_szau_lname,
         sizeof(m_szau_lname), lau_lnameStatus, FALSE)
   ADO_VARIABLE_LENGTH_BINDING_ENTRY(2, adVarChar, m_szau_fname,
         sizeof(m_szau_fname), lau_fnameStatus, TRUE)
END_ADO_BINDING()

public:
   CHAR   m_szau_lname[41];
   ULONG   lau_lnameStatus;
   CHAR   m_szau_fname[41];
   ULONG   lau_fnameStatus;
};

VOID   main()
   {
   HRESULT hr;
   IADORecordBinding   *picRs = NULL;

   ::CoInitialize(NULL);

   try
      {
      _RecordsetPtr pRs.CreateInstance(__uuidof(Recordset));      CCustomRs rs;

      pRs->Open("select FirstName, LastName, Age from Employees",
         "dsn=pubs;uid=sa;pwd=;",
         adOpenStatic, adLockOptimistic, adCmdUnknown);

      if (FAILED(hr = pRs->QueryInterface(__uuidof(IADORecordBinding),
            (LPVOID*)&picRs)))
         _com_issue_error(hr);

      if (FAILED(hr = picRs->BindToRecordset(&rs)))
         _com_issue_error(hr);

      while (VARIANT_FALSE == pRs->EndOfFile)
         {
      // Process data in the CCustomRs C++ instance variables.

         printf("\a\tName = %s \t%s",
            (lau_fnameStatus == adFldOK ? m_szau_fname : "<NULL>"),
            (lau_lnameStatus == adFldOK ? m_szau_lname): "<NULL>"));

      // Change the current row of the Recordset.
      // Recordset data for the new current row will automatically be
      // extracted and placed in the CCustomRs C++ instance variables.

         pRs->MoveNext();
         }
      }
   catch (_com_error &e)
      {
      dump_com_error(e);
      }

   if (picRs)
      picRs->Release();

   CoUninitialize();
   };


Hierarchical Cursors and Data Shaping

You are familiar with visual controls, such as the File Open dialog box, that show folders and files in a hierarchical fashion. That's a good picture to keep in mind when you think about the new Hierarchical Cursor feature.

This feature allows you to define a child Recordset object as the value of a field in a parent Recordset. A typical application for this feature is to query "Customer" and "Order" databases, then display all the orders for each customer.

The new Shape data manipulation syntax built into the ADO Client Cursor Engine allows you to make queries that result in a hierarchical Recordset. You can then gain access to the child Recordset programmatically or through an appropriate visual control.


Hierarchical Cursors and Data Shaping Summary

ADO 2.0 introduces the Hierarchical Cursor feature, which enables you to define a child Recordset object as the value of a field in a parent Recordset.

Here is a useful way to envision Hierarchical Cursors. Imagine a visual control, such as the File Open dialog, that shows files and subdirectories in a hierarchical fashion. Think of each directory as a Recordset object; each file within a directory as a Field object; and each subdirectory within a directory as a Field object whose value is another Recordset.

ADO 2.0 also introduces a new Shape data manipulation language syntax, which allows you to make queries that result in a hierarchical Recordset. A Shape language command is issued just as you would issue any ADO command string.

The Shape language is built into the ADO Client Cursor Engine. We will call the process of creating it Data Shaping.

The Shape language enables you to make hierarchical Recordset objects in two ways. The first appends a child Recordset to the parent Recordset, while the second computes an aggregate operation on a child Recordset and generates a parent Recordset.

You can nest hierarchical Recordset objects to any depth you require (that is, create children Recordset objects of children Recordset objects, and so on).

You can access the resulting hierarchical Recordset programmatically or through an appropriate visual control.

The Shape language is relatively difficult to write. Therefore, Microsoft provides a visual tool that generates Shape commands for you (see the Visual Basic topic, "The Data Environment Designer") and another visual tool that displays hierarchical cursors (see the Visual Basic topic, "Using the Microsoft Hierarchical Flexgrid Control").


Required Providers for Data Shaping

An OLE DB data source provider must supply data that will be passed to another provider, which will perform the Data Shaping. The data source provider is specified in the Connection object connect string as "Shape Provider=YourDataSource". The provider supplying Data Shaping support is specified in the Connection object Provider property as "MSDataShape".

Example

Dim cnn As New ADODB.Connection
cnn.Provider = "MSDataShape"
cnn.Open "Shape Provider=MSDASQL;DSN=vfox;uid=sa;pwd=vfox;database=pubs”


Shape Commands in General

A Shape command defines the structure of an hierarchical Recordset, and the commands necessary to populate it with data.

A part of the Shape command is a query issued to the underlying data provider which returns a Recordset object. The query's syntax depends on the requirements of the underlying data provider. This will usually be Structured Query Language (SQL), although ADO doesn't require the use of any particular query language.

You could use an SQL JOIN clause to relate two tables; however, a hierarchical Recordset will represent the information more efficiently. Each row of a Recordset created by a JOIN repeats information redundantly from one of the tables. A hierarchical Recordset has only one parent Recordset for each of multiple child Recordset objects.

You can use parentheses to group parts for clarification.

Shape commands can be issued only by Recordset objects.

Shape commands can be nested. That is, the parent-command or child-command may itself be another Shape command.

For information about navigating a hierarchical Recordset, see Accessing Rows in a Hierarchical Recordset.


Shape Append Command

The Shape APPEND command assigns a child Recordset to the Value property of Field objects in a parent Recordset.

Syntax

"SHAPE {parent-command} [[AS] table-alias]

APPEND {child-command}

RELATE(parent-column TO child-column)"

Description of parts

The parts of this command are:

  • parent-command, child-command—A query command that returns a Recordset object. The command is issued to the underlying data provider, and its syntax depends on the requirements of that provider. This will typically be Structured Query Language (SQL), although ADO doesn't require any particular query language.

  • parent-column—A column in the Recordset returned by the parent-command.

  • child-column—A column in the Recordset returned by the child-command.

  • table-alias—An alias used to refer to the Recordset returned by the parent-command.

Operation

The Client Cursor Engine will issue the parent-command to the provider, which will return a parent Recordset. Then the child-command will be issued, which will return a child Recordset.

For example, the parent-command could return a Recordset of customers for a company from a Customers database, and the child-command could return a Recordset of orders for all customers from an Orders database.

The parent and child Recordset objects must have a column in common. The columns are named in the RELATE clause, parent-column first, then child-column. The columns may have different names in their respective Recordset objects, but must refer to the same information in order to specify a meaningful relation.

For example, the Customers and Orders recordsets could have CustomerID and BuyerID fields in common.

The Client Cursor Engine internally creates a new column and literally appends it to the parent Recordset. The values of the fields in the new column are references to rows in the child recordset which satisfy the RELATE clause.

The appended column will be automatically named "chapter" and be of data type adChapter. If you wish to navigate through the child Recordset, specify the appended column in the Recordset object Fields collection and retrieve the Recordset from the Field object Value property. Assign the retrieved Recordset to an empty Recordset object, then navigate through that Recordset as you would any other.

Parameterized Commands

Shape commands may be parameterized. For example, you can specify the following:

"SHAPE {SELECT * FROM customer}
APPEND {SELECT * FROM orders WHERE cust_id = ?}
RELATE (cust_id TO PARAMETER 0)"

In this case, parent and child tables happen to have a column name in common, cust_id. The child-command has a placeholder (that is, "?"), to which the RELATE clause refers (that is, "...PARAMETER 0". In effect, the relation is between the explicitly identified parent-column, and the child-column implicitly identified by the placeholder).

When the Shape command is executed, this is what happens in effect:

  • An empty column is appended to the parent Recordset.

  • The parent-command is executed and returns a row from the customer table.

  • The value of the customer.cust_id column replaces the placeholder and the child-command is executed.

  • All the rows from the orders table where the orders.cust_id column matches the customer.cust_id column are retrieved.

  • A reference to the retrieved child rows is placed in the current row of the column appended to the parent Recordset.

  • Then the next parent row is retrieved from the customer table and the cycle repeats until all rows are retrieved.


Shape Compute Command

A Shape COMPUTE command executes an aggregate function on the rows of the child Recordset to generate a parent Recordset, then assigns the child Recordset to the Value property of Field objects in the generated parent Recordset.

Syntax

"SHAPE {child-command} [[AS] table-alias]

COMPUTE aggregate-command-field-list

[BY grp-field-list]"

Description of parts

The parts of this command are:

  • child-command—A query command that returns a Recordset object. The command is issued to the underlying data provider, and its syntax depends on the requirements of that provider. This will typically be Structured Query Language (SQL), although ADO doesn't require any particular query language.

  • table-alias—An alias used to refer to the Recordset returned by the child-command.

  • aggregate-command-field-list—A list of fields operated on by an aggregate function. The Recordset may be referred to by its table-alias in the aggregate function. You can also create a column to use as you desire, with the NEW operator.
Aggregate Function | Description
SUM(<alias>.<child-field-name>) | Calculates the sum of all values in the specified field.
AVG(<alias>.<child-field-name>) | Calculates the average of all values in the specified field.
MAX(<alias>.<child-field-name>) | Calculates the maximum value in the specified field.
MIN(<alias>.<child-field-name>) | Calculates the minimum value in the specified field.
COUNT(<alias>[.<child-field-name>]) | Counts the number of rows in the specified field.
STDEV(<alias>.<child-field-name>) | Calculates the standard deviation in the specified field.
ANY(<alias>.<child-Field-name>) | The value of a column (where the value of the column is the same for all rows).
CALC(expression) | Calculates an arbitrary expression, but only on the current row.
NEW (field type [(width | scale [,precision])] | Adds an empty column of the specified type to the Recordset.

  • grp-field-list—A list of columns specifying the order of rows in the child Recordset. If the BY clause is not specified, then only the result of the aggregate function will be returned. If the BY clause is specified, the child Recordset will be appended to the generated parent Recordset.

Operation

The Client Cursor Engine will issue the child-command to the provider, which will return a child Recordset.

The COMPUTE clause specifies an aggregate operation to be executed on specified columns (aggregate-command-field-list) of the child Recordset, such as summing all the values in a column, or finding the maximum value in a column. The aggregate operation creates a parent Recordset.

If there is no BY clause, then the Shape command concludes. If there is a BY clause, the child Recordset will be appended to the parent Recordset. The rows of the child Recordset will be arranged in groups as specified in the grp-field-list.

For example, assume you have a table, Demographics, consisting of State, City, and Population fields (the population figures are solely for illustration).

State | City | Population
WA | Seattle | 700,000
OR | Medford | 200,000
OR | Portland | 600,000
CA | Los Angeles | 900,000
CA | San Diego | 400,000
WA | Tacoma | 500,000
OR | Corvallis | 300,000

Now, issue this Shape command:

    rst.Open    "SHAPE  {select * from demographics}
               COMPUTE (SUM(population)) AS chapter
               BY state",
               connection

This command opens a parent Recordset. Because you specified the BY clause, a hidden column was appended, with references to Recordset objects that provide detail for each row in the parent Recordset.

The child Recordset detail rows will be grouped, but not in any particular order. That is, the groups will not automatically be in alphabetical or numerical order.

An arbitrary name will be generated for the appended column.

You can now navigate the opened parent Recordset, and access the child detail Recordset objects. See Accessing Rows in a Hierarchical Recordset.

Resultant Parent and Child Detail Recordsets

Parent

State | SUM (Population) | (Appended field)
CA | 1,300,000 | Reference to child1
WA | 1,200,000 | Reference to child2
OR | 1,100,000 | Reference to child3

Child1

State | City | Population
CA | Los Angeles | 900,000
CA | San Diego | 400,000

Child2

State | City | Population
WA | Seattle | 700,000
WA | Tacoma | 500,000

Child3

State | City | Population
OR | Medford | 200,000
OR | Portland | 600,000
OR | Corvallis | 300,000


Accessing Rows in a Hierarchical Recordset

The following example shows the steps necessary to access rows in a hierarchical Recordset:

  1. Recordset objects from the authors and titleauthors tables are related by author ID.

  2. The outer loop displays each author's first and last name, state, and identification.

  3. The appended Recordset for each row is retrieved from the Fields collection and assigned to rsChapter.

  4. The inner loop displays four fields from each row in the appended Recordset.

Example

Sub datashape()
    Dim cnn As New ADODB.Connection
    Dim rst As New ADODB.Recordset
    Dim rsChapter As Variant

    cnn.Provider = "MSDataShape"
    cnn.Open    "Data Provider=MSDASQL;" & _
               "DSN=vfox;uid=sa;pwd=vfox;database=pubs”
'STEP 1
    rst.StayInSync = FALSE
    rst.Open    "SHAPE  {select * from authors}
               APPEND ({select * from titleauthor} AS chapter
               RELATE au_id TO au_id)",
               cnn
'STEP 2
    While Not rst.EOF
        Debug.Print    rst("au_fname"), rst("au_lname"),
                     rst("state"), rst("au_id")
'STEP 3
        Set rsChapter = rst("chapter")
'STEP 4
        While Not rsChapter.EOF
            Debug.Print rsChapter(0), rsChapter(1),
                        rsChapter(2), rsChapter(3)
            rsChapter.MoveNext
        Wend
        rst.MoveNext
    Wend
End Sub


Formal Shape Grammar

This is the formal grammar for creating any Shape command.

  • Required grammatical terms are text strings delimited by angle brackets ("<>").

  • Optional terms are delimited by square brackets ("[ ]").

  • Alternatives are indicated by a virgule ("|").

  • Repeating alternatives are indicated by an ellipsis ("...").

  • Alpha indicates a string of alphabetical letters.

  • Digit indicates a string of numbers.

  • Unicode-digit indicates a string of unicode digits.

  • All other terms are literals.
Term Definition
<shape-command>

SHAPE <table-exp> [[AS] <alias>][<shape-action>]

<table-exp>

{<native-sql-statement>} |
(<shape-command>)

<shape-action>

APPEND <aliased-field-list> |
COMPUTE <aliased-field-list>
   [BY <field-list> [[AS] <alias>]] |
BY <field-list> [[AS] <alias>]

<aliased-field-list>

<aliased-field> [, <aliased-field...]

<aliased-field>

<field-exp> [[AS] <alias>]

<field-exp>

(<relation-exp>) |
<calculated-exp>

<relation_exp>

<table-exp> [[AS] <alias>]
   RELATE <relation-cond-list>

<relation-cond-list>

<relation-cond> [, <relation-cond>...]

<relation-cond>

<field-name> TO <child-ref>

<child-ref>

<field-name> |
PARAMETER <param-ref>

<param-ref>

<number>

<field-list>

<field-name [, <field-name>]

<calculated-exp>

SUM(<qualified-field-name>) |
AVG(<qualified-field-name>) |
MIN(<qualified-field-name>) |
MAX(<qualified-field-name>) |
COUNT(<alias>) |
STDEV(<qualified-field-name>) |
ANY(<qualified-field-name>) |
CALC(<expresion>)

<qualified-field-name>

<alias>.<field-name> |
<field-name>

<alias>

<quoted-name>

<field-name>

<quoted-name>

<quoted-name>

"<string>" |
'<string>' |
<name>

<name>

alpha [ alpha | digit | _ | # ...]

<number>

digit [digit...]

<string>

unicode-char [unicode-char...]

<expression>

An expression recognized by the Jet Expression service whose operands are other non-CALC columns in the same row.


DataFactory Customization

Before ADO 2.0, you were limited in what you could do using the default DataFactory object provided by Remote Data Service. The DataFactory could connect to a data source and execute a query command, or update the data source with a Recordset object.

With this release, an extension, or handler, can override the default DataFactory connection or command with parameters supplied in a customization file. In addition, the ability of an administrator or guest to read or write data is governed by access rights. You can also design your own custom business objects to use a handler.


DataFactory Customization Summary

  • The default behavior of the client/server RDSServer.DataFactory object is limited to queries and updates.

  • The new Handler server object works with the DataFactory and extends its functionality.

  • The server administrator controls the Handler by specifying parameters in a customization file.

  • The customization file is divided into sections, each marked with a section header. A section is invoked when strings in the client connect or command strings match an identifier string in the section header. The contents of a matched section are applied to the client parameters.

  • The content of a section can replace, expand, or "turn off" client connect or command parameters, or assign temporary read/write privileges to a particular user.

  • In addition, a section type is available for specifying an error logging file.


Customizing the RDSServer.DataFactory Object

Remote Data Service (RDS) provides a way to easily perform data access in a three-tier client/server system. A client data control specifies connect and command string parameters to perform a query on a remote data source, or connect string and Recordset object parameters to perform an update.

The parameters are passed to a server program, which actually performs the data-access operation on the remote data source. RDS provides a default server program called the RDSServer.DataFactory object. The RDSServer.DataFactory object returns any Recordset object produced by a query to the client.

However, the RDSServer.DataFactory is limited to performing queries and updates. It cannot perform any validation or processing on the connect or command strings.

Starting with ADO 2.0, you can specify the DataFactory to work in conjunction with another type of server program called a Handler. The Handler can modify client connect and command strings before they are used to access the data source. In addition, the Handler can enforce access rights, which govern the ability of the client to read and write data to the data source.

The parameters the Handler uses to modify client parameters and access rights are specified in a customization file. The Handler parameters are specified in sections of the customization file.


Understanding the Customization File

Each section header in the customization file consists of square brackets ([]) containing a type and operand. The four section types are indicated by the literal strings connect, sql, userlist, or logs. The operand is the literal string, default, a user-specified identifier, or nothing.

Therefore, each section is marked with one of the following section headers:

[ connect   default      ]
[ connect   identifier   ]
[ sql         default      ]
[ sql         identifier   ]
[ userlist   identifier   ]
[ logs                  ]

The section headers have the following parts:

Part | Description
connect | Literal string—This section modifies a connect string.
sql | Literal string—This section modifies a command string.
userlist | Literal string—This section modifies the access rights of a specific user.
logs | Literal string—This section specifies a log file that records operational errors.
default | Literal string—This section is used if no identifier is specified or found.
identifier A string that matches a string in the connect or command string.
  • Use this section if the section header contains connect and the identifier string is found in the connect string.

  • Use this section if the section header contains sql and the identifier string is found in the command string.

  • Use this section if the section header contains userlist and the identifier string matches a connect section identifier.

The DataFactory calls the Handler, passing client parameters. The Handler searches for whole strings in the client parameters that match identifiers in the appropriate section headers. If a match is found, the contents of that section are applied to the client parameter.

A particular section is used under the following circumstances:

  • A connect section is used if the value part of the client connect string keyword, "Data Source=value", matches a connect section identifier.

  • A sql section is used if the client command string contains a string that matches a sql section identifier.

  • A connect or sql section with a default operand will be used if there is no matching identifier.

  • A userlist section is used if the userlist section identifier matches a connect section identifier. If there is a match, the contents of the userlist section are applied to the connection governed by the connect section.

  • If the string in a connect or command string does not match the identifier in any connect or sql section header, and there is no connect or sql section header with a default operand, then the client string is used without modification.

  • The logs section will be used whenever the DataFactory is in operation.


Customization File Connect Section

A connect section can contain:

  • A new connect string that replaces the client connection string.

  • A default access entry that specifies the default read and write operations allowed on this connection. If there is no default access entry in the section, the section will be ignored.

Syntax

A replacement connection string entry is of the form:

Connect=connectionString

A default access entry is of the form:

Access=accessRight

Part | Description
Connect | Literal string—Indicates this is a connection string entry.
connectionString | A string that replaces the whole client connection string.
Access | Literal string—Indicates this is an access entry.
accessRight One of the following access rights:
  • NoAccess—User cannot access the data source.

  • ReadOnly—User can read the data source.

  • ReadWrite—User can read or write the data source.


Customization File SQL Section

The sql section can contain:

  • A new SQL string that replaces the client command string. If there is no SQL string in the section, the section will be ignored.

The new SQL string may be parameterized. That is, parameters in the sql section SQL string (designated by the '?' character) can be replaced by corresponding arguments in an identifier in the client command string (designated by a parenthesized, comma-delimited list). The identifier and parenthesized argument list behave like a function call.

For example, assume the client command string is "CustomerByID(4)", the SQL section header is [SQL CustomerByID], and the new SQL section string is "SELECT * FROM Customers WHERE CustomerID = ?". The Handler will generate "SELECT * FROM Customers WHERE CustomerID = 4" and use that string to query the data source.

If the new SQL statement is the null string ("") then the section is ignored.

If the new SQL statement string is invalid, then the execution of the statement will fail. The client parameter is effectively ignored. You can do this on purpose to "turn off" all client SQL commands by specifying:

[SQL default]
SQL = " "

Syntax

A replacement SQL string entry is of the form:

SQL=sqlString

Part | Description
SQL | Literal string—Indicates this is a SQL section entry.
sqlString | A SQL string that replaces the client string.


Customization File UserList Section

This userlist section pertains to the connect section with the same section identifier operand.

This section can contain:

  • A user access entry, which specifies access rights for the specified user and overrides the default access entry in the matching connect section.

Syntax

A user access entry is of the form:

userName=accessRights

Part | Description
userName | The user name of the person employing this connection. Valid user names are established with the IIS Service Manager dialog.
accessRights One of the following access rights:
  • NoAccess—User cannot access the data source.

  • ReadOnly—User can read the data source.

  • ReadWrite—User can read or write the data source.


Customization File Logs Section

This section contains a log file entry, which specifies the name of a file that records errors during the operation of the DataFactory.

Syntax

A log file entry is of the form:

err=FileName

Part | Description
err | Literal string—Indicates this is a log file entry.
FileName | A complete path and file name. The typical file name is c:\msdfmap.log.

The log file will contain the user name, HRESULT, date, and time of each error.


Required Client Settings

Specify the following settings to use a custom DataFactory Handler.

  • Specify "Provider=MS Remote" in the Connection object Provider property or the Connection object connect string "Provider=" keyword.

  • Set the CursorLocation property to adUseClient.

  • Specify the name of the Handler to use in the RDS.DataControl Handler property, or the Recordset object connect string "Handler=" keyword. (You cannot set the Handler in the Connection object connect string.)

    RDS provides a default Handler on the server named MSDFMAP.Handler. (The default customization file is named MSDFMAP.INI.)

Example

Assume the following sections in MSDFMAP.INI, and that the data source name, AdvWorks, has been previously defined:

[connect CustomerDataBase]
Access=ReadWrite
Connect="DSN=AdvWorks"

[sql CustomerById]
SQL="SELECT * FROM Customers WHERE CustomerID = ?"

In Visual Basic:

RDS.DataControl Version:

Dim dc as New RDS.DataControl
Set dc.Handler = "MSDFMAP.Handler"
Set dc.Server = "http://YourServer"
Set dc.Connect = "Data Source=CustomerDatabase"
Set dc.SQL = "CustomerById(4)"
dc.Refresh

Recordset Version:

Dim rs as New ADODB.Recordset
rs.CursorLocation = adUseClient

Specify either the Handler property or keyword; the Provider property or keyword; and the CustomerById and CustomerDatabase identifiers. Then open the Recordset object.

rs.Open "CustomerById(4)", "Handler=MSDFMAP.Handler; Provider=MS Remote;Data Source=CustomerDatabase;Remote Server=http://YourServer"


Writing Your Own Customized Handler

You may want to write your own Handler if you are an IIS server administrator who wants the default RDS support, but more control over user requests and access rights.

The MSDFMAP.Handler implements the IDataFactoryHandler interface.

IDataFactoryHandler Interface

This interface has two methods, GetRecordset and Reconnect. Both methods require the CursorLocation property be set to adUseClient.

Both methods take arguments that appear after the first comma in the "Handler=" keyword. For example, "Handler=progid,arg1,arg2;" will pass an argument string of "arg1,arg2", and "Handler=progid" will pass a NULL argument.

GetRecordset Method

This function is used to query the data source and create a new Recordset object using the arguments provided. The Recordset must be opened with adLockBatchOptimistic, and must not be opened asynchronously.

Syntax

conn The connection string.

args Arguments for the handler.

query The command text for making a query.

ppRS Pointer where the Recordset should be returned.

Reconnect Method

This function is used to update the data source. It will create a new Connection object and attach the given Recordset.

Syntax

conn The connection string.

args Arguments for the handler.

pRS A Recordset object.

msdfhdl.idl

This is the interface definition for IdataFactoryHandler that appears in the msdfhdl.idl file.

[
  uuid(D80DE8B3-0001-11d1-91E6-00C04FBBBFB3),
  version(1.0)
]
library MSDFHDL
{
    importlib("stdole32.tlb");
    importlib("stdole2.tlb");

    // TLib : Microsoft ActiveX Data Objects 2.0 Library
    // {00000200-0000-0010-8000-00AA006D2EA4}
    #ifdef IMPLIB
    importlib("implib\\x86\\release\\ado\\msado15.dll");
    #else
    importlib("msado20.dll");
    #endif

    [
      odl,
      uuid(D80DE8B5-0001-11d1-91E6-00C04FBBBFB3),
      version(1.0)
    ]
    interface IDataFactoryHandler : IUnknown
    {
HRESULT _stdcall GetRecordset(
      [in] BSTR conn,
      [in] BSTR args,
      [in] BSTR query,
      [out, retval] _Recordset **ppRS);

// DataFactory will use the ActiveConnection property
// on the recordset after calling Reconnect.
   HRESULT _stdcall Reconnect(
      [in] BSTR conn,
      [in] BSTR args,
      [in] _Recordset *pRS);
    };
};


Getting Started with ADO 2.0

This section contains a series of topics that you can read in a prescribed order. Just click the link to the next topic at the end of each topic. The following topics are included:

  • Solutions for Local Data Access

  • Basic ADO Programming Model

  • The ADO Programming Model in Detail

  • ADO Programming Model with Objects

  • ADO Object Model Summary

  • Solutions for Remote Data Access

  • Basic RDS Programming Model

  • The RDS Programming Model in Detail

  • RDS Programming Model with Objects

  • The RDS Object Model Summary

Next … Solutions for Local Data Access.


Solutions for Local Data Access

The Issue

You want a simple, consistent application programming interface (API) that enables applications to gain access to and modify a wide variety of data sources. A data source may be as simple as a text file, complex as a cluster of heterogeneous databases, or something yet to be invented. Furthermore, the API should not presume the means of gaining access to and manipulating the data source.

Although these are your specific requirements, the typical data source is a relational database that supports the Open Database Connectivity (ODBC) standard and is manipulated with commands written in Structured Query Language (SQL).

The general solution Microsoft offers to this problem is OLE DB, a set of Component Object Model (COM) interfaces that provide uniform access to data stored in diverse information sources. However, the OLE DB application programming interface is designed to provide optimal functionality in a wide variety of applications; it does not meet the requirement for simplicity.

You need an API that is a bridge between the application and OLE DB. ActiveX® Data Objects (ADO) is that bridge.

The Solution

ADO defines a programming model—the sequence of activities necessary to gain access to and update a data source. The programming model summarizes the entire functionality of ADO.

The programming model suggests an object model—the set of objects that correspond to and implement the programming model. Objects possess methods that perform some operation on data, and properties that either represent some attribute of the data or control the behavior of some object method.

Associated with objects are events, which are notifications that some operation has occurred, or is about to occur.

Next … Basic ADO Programming Model.


Basic ADO Programming Model

ADO provides the means for you to perform the following sequence of actions:

  1. Connect to a data source. Optionally, you can ensure that all changes to the data source occur either successfully or not at all.

  2. Specify a command to gain access to the data source, optionally with variable parameters, or optionally optimized for performance.

  3. Execute the command.

  4. If the command causes data to be returned in the form of rows in a table, store the rows in a cache that you can easily examine, manipulate, or change.

  5. If appropriate, update the data source with changes from the cache of rows.

  6. Provide a general means to detect errors (usually as a result of making a connection or executing a command).

Typically, you will employ all these steps in the programming model. However, it's worth noting that ADO is flexible enough that you can do useful work by executing just part of the model. For example, you could store data from a file directly into a cache of rows, then use ADO resources merely to examine the data.

Next … The ADO Programming Model in Detail.


The ADO Programming Model in Detail

The following elements are key parts of the ADO programming model:

  • Connection

  • Command

  • Parameter

  • Recordset

  • Field

  • Error

  • Property

  • Collection

  • Event

Connection

Access from your application to a data source is through a connection, the environment necessary for exchanging data. Your application can gain access to a data source directly (sometimes called a two-tier system), or indirectly (sometimes called a three-tier system) through an intermediary like the Microsoft® Internet Information Server.

The object model embodies the concept of a connection with the Connection object.

A transaction delimits the beginning and end of a series of data access operations that transpire across a connection. ADO ensures that changes to a data source resulting from operations in a transaction either all occur successfully, or not at all.

If you cancel the transaction or one of its operations fails, then the ultimate result will be as if none of the operations in the transaction had occurred. The data source will be as it was before the transaction began.

The object model does not explicitly embody the concept of a transaction, but represents it with a set of Connection object methods.

ADO accesses data and services from OLE DB providers. The Connection object is used to specify a particular provider and any parameters. For example, Remote Data Service (RDS) can be invoked explicitly or it can be invoked implicitly with the "MS Remote" provider. (Please see the RDS Tutorial for an example of invoking RDS via the "MS Remote" provider in step 2.)

Command

A command issued across an established connection manipulates the data source in some way. Typically the command adds, deletes, or updates data in the data source, or retrieves data in the form of rows in a table.

The object model embodies the concept of a command with the Command object. The existence of a Command object gives ADO the opportunity to optimize the execution of the command.

Parameter

Often, commands require variable parts, parameters, that can be altered before you issue the command. For example, you could issue the same data retrieval command repeatedly, but each time vary your specification of the information to be retrieved.

Parameters are especially useful for executing commands that behave like functions. In this case you know what the command does, but not necessarily how it works. For example, you issue a bank transfer command that debits one account and credits another. You specify the amount of money to be transferred as a parameter.

The object model embodies the concept of a parameter with the Parameter object.

Recordset

If your command is a query that returns data as rows of information in a table (that is, it is a row-returning query), then those rows are placed in local storage.

The object model embodies this storage as a Recordset object. However, there is no object that represents a single row of a Recordset.

The Recordset is the primary means of examining and modifying data in the rows. The Recordset object allows you to:

  • Specify which rows are available for examination.

  • Traverse the rows.

  • Specify the order in which the rows may be traversed.

  • Add, change, or delete rows.

  • Update the data source with changed rows.

  • Manage the overall state of the Recordset.

Field

A row of a Recordset consists of one or more fields. If you envision the Recordset as a two-dimensional grid, the fields line up to form columns. Each field (column) has among its attributes a name, a data type, and a value. It is this value that contains the actual data from the data source.

The object model embodies a field as a Field object.

In order to modify data in the data source, you modify the value of Field objects in Recordset rows. Ultimately, changes to a Recordset are propagated to the data source. As an option, the transaction management methods on the Connection object can guarantee that the changes succeed or fail in unison.

Error

Errors can occur at any time in your application, usually as the result of not being able to establish a connection, execute a command, or perform an operation on an object in a suitable state (for example, attempting to use a Recordset object that has not been initialized).

The object model embodies an error as an Error object.

Any given error produces one or more Error objects. The next error that occurs will discard the previous set of Error objects.

Property

Each ADO object has a set of unique properties that either describe or control the behavior of that object.

There are two types of properties: built-in and dynamic. Built-in properties are part of the ADO object and are always available. Dynamic properties are added to the ADO object's Properties collection by the underlying data provider, and exist only while that provider is being used.

The object model embodies a property as a Property object.

Collection

ADO provides collections, a type of object that conveniently contains other objects of a particular type. The objects in the collection can be retrieved with a collection method either by name, as a text string, or by ordinal, as an integer number.

ADO provides four types of collections:

  • The Connection object has the Errors collection, which contains all Error objects created in response to a single failure involving the data source.

  • The Command object has the Parameters collection, which contains all Parameter objects that apply to that Command object.

  • The Recordset object has the Fields collection, which contains all Field objects that define the columns of that Recordset object.

  • In addition, the Connection, Command, Recordset, and Field objects all have a Properties collection, which contains all the Property objects that apply to their respective containing objects.

ADO objects possess properties where you set or retrieve values with common data types like INTEGER, CHARACTER, or BOOLEAN. However, it's useful to think of certain properties as returning values of data type "COLLECTION OBJECT." The collection object, in turn, has methods to store and retrieve other objects suitable for the collection.

For example, you can think of the Recordset object as having a Properties property that returns a collection object. That collection object has methods to store and retrieve Property objects describing attributes of that Recordset.

Events

ADO 2.0 introduces the concept of events to the programming model. Events are notifications that certain operations are about to occur, or have already occurred. You can use events, in general, to efficiently orchestrate an application consisting of several asynchronous tasks.

The object model does not explicitly embody events, but represents them as calls to event handler routines.

Event handlers called before the operation starts offer you the opportunity to examine or modify the operation parameters, then either cancel or allow the operation to complete.

Event handlers called after an operation completes notify you at the completion of an asynchronous operation. ADO 2.0 introduces several operations that have been enhanced to optionally execute asynchronously. For example, an application that starts an asynchronous Recordset.Open operation is notified by an execution complete event when the operation concludes.

There are two families of events:

  • ConnectionEvents—Events are issued when transactions on a connection begin, are committed, or rolled back; when Commands execute; and when Connections start or end.

  • RecordsetEvents—Events are issued to report the progress of data retrieval; when you navigate through the rows of a Recordset object; when you change a field in a row of a recordset, change a row in a recordset, or make any change in the entire recordset.

Next … ADO Programming Model with Objects.


ADO Programming Model with Objects

The goal of ADO is to gain access to, edit, and update data sources, and the programming model embodies the sequence of activities necessary to accomplish this goal. ADO provides classes and objects to perform each of the following activities:

  • Make a connection to a data source (Connection). Optionally, begin a transaction.

  • Optionally, create an object to represent an SQL command (Command).

  • Optionally, specify columns, tables, and values in the SQL command as variable parameters (Parameter).

  • Execute the command (Command, Connection, or Recordset).

  • If the command is row-returning, store the rows in a cache (Recordset).

  • Optionally, create a view of the cache so you can sort, filter, and navigate the data (Recordset).

  • Edit the data, by either adding, deleting, or changing rows and columns (Recordset).

  • If appropriate, update the data source with changes from the cache (Recordset).

  • If a transaction was used, accept or reject the changes made during the transaction. End the transaction (Connection).

Next … ADO Object Model Summary.


ADO Object Model Summary

ADO Object Summary

Object | Description
Connection | Enables exchange of data.
Command | Embodies an SQL statement.
Parameter | Embodies a parameter of an SQL statement.
Recordset | Enables navigation and manipulation of data.
Field | Embodies a column of a Recordset object.
Error | Embodies an error on a connection.
Property | Embodies a characteristic of an ADO object.

ADO Collection Summary

Collection | Description
Errors | All the Error objects created in response to a single failure on a connection.
Parameters | All the Parameter objects associated with a Command object.
Fields | All the Field objects associated with a Recordset object.
Properties | All the Property objects associated with a Connection, Command, Recordset or Field object.

ADO Event Handler Summary

ConnectionEvents | Description
BeginTransComplete, CommitTransComplete, RollbackTransComplete | Transaction Management—Notification that the current transaction on the connection has started, committed, or rolled back.
WillConnect, ConnectComplete, Disconnect | Connection Management—Notification that the current connection will start, or has started or ended.
WillExecute, ExecuteComplete | Command Execution Management—Notification that the execution of the current command on the connection will start, or has ended.
InfoMessage | Informational—Notification that there is additional information about the current operation.

RecordsetEvents | Description
FetchProgress, FetchComplete | Retrieval Status—Notification of the progress of a data retrieval operation, or that the retrieval operation has completed.
WillChangeField, FieldChangeComplete | Field Change Management—Notification that the value of the current field will change, or has changed.
WillMove, MoveComplete, EndOfRecordset | Navigation Management—Notification that the current row position in a Recordset will change, has changed, or has reached the end of the Recordset.
WillChangeRecord, RecordChangeComplete | Row Change Management—Notification that something in the current row of the Recordset will change, or has changed.
WillChangeRecordset, RecordsetChangeComplete | Recordset Change Management—Notification that something in the current Recordset will change, or has changed.

Next … Solutions for Remote Data Access.


Solutions for Remote Data Access

The Issue

ADO enables your application to directly gain access to and modify data sources (sometimes called a two-tier system). For example, if your connection is to the data source that contains your data, then that is a direct connection in a two-tier system.

However, you may want to access data sources indirectly through an intermediary such as Microsoft Internet Information Server (IIS). This arrangement is sometimes called a three-tier system. IIS is a client/server system that provides an efficient way for a local, or client, application to invoke a remote, or server, program across the Internet or an intranet. The server program gains access to the data source and optionally processes the acquired data.

For example, your intranet Web page contains an application written in Microsoft® Visual Basic®, Scripting Edition (VBScript), which connects to IIS. IIS in turn connects to the actual data source, retrieves the data, processes it in some way, then returns the processed information to your application.

In this example, your application never directly connected to the data source; IIS did. And IIS accessed the data by means of ADO.

Note The client/server application doesn't have to be based on the Internet or an intranet (that is, Web-based)—it could consist solely of compiled programs on a local area network. However, the typical case is a Web-based application.

Because some visual control, such as a grid, check box, or list, may use the returned information, the returned information must be easily used by a visual control.

You want a simple, efficient application programming interface that supports three-tier systems, and returns information as easily as if it had been retrieved on a two-tier system. Remote Data Service (RDS) is this interface.

The Solution

RDS defines a programming model—the sequence of activities necessary to gain access to and update a data source—to gain access to data through an intermediary such as Internet Information Server. The programming model summarizes the entire functionality of RDS.

The programming model suggests an object model—the set of objects that correspond to and implement the programming model. Objects possess methods that perform some operation on data, and properties that either represent some attribute of the data or control the behavior of some object method.

Associated with objects are events, which are notifications that some operation has occurred, or is about to occur.

Next … Basic RDS Programming Model.


Basic RDS Programming Model

RDS addresses applications that exist in the following environment: A client application specifies a program that will execute on a server and the parameters required to return the desired information. The program invoked on the server gains access to the specified data source, retrieves the information, optionally processes the data, then returns the resulting information to your client application in a form that it can easily use.

RDS provides the means for you to perform the following sequence of actions:

  1. Specify the program to be invoked on the server, and obtain a way to refer to it from the client. (This reference is sometimes called a proxy. It represents the remote server program. The client application will "call" the proxy as if it were a local program, but it actually invokes the remote server program.)

  2. Invoke the server program. Pass parameters to the server program that identify the data source and the command to issue. (The server program actually uses ADO to gain access to the data source. ADO makes a connection with one of the given parameters, then issues the command specified in the other parameter.)

  3. The server program obtains a Recordset object from the data source. Optionally, the Recordset object is processed on the server.

  4. The server program returns the final Recordset object to the client application.

  5. On the client, the Recordset object is put into a form that can be easily used by visual controls.

  6. Any modifications to the Recordset object are sent back to the server program, which uses them to update the data source.

This programming model contains certain convenience features. If you don’t need a complex server program to access the data source, and if you provide the required connection and command parameters, RDS will automatically retrieve the specified data with a simple, default server program.

However, if you need more complex processing you can specify your own custom server program. For example, because a custom server program has the full power of ADO at its disposal, it could connect to several different data sources, combine their data in some complex way, then return a simple, processed result to the client application.

Finally, if your needs are somewhere in between, ADO 2.0 now supports customizing the behavior of the default server program.

Next … The RDS Programming Model in Detail.


The RDS Programming Model in Detail

The following elements are key parts of the RDS programming model:

  • RDS.DataSpace

  • RDSServer.DataFactory

  • RDS.DataControl

  • Event

RDS.DataSpace

Your client application must specify the server and the server program to invoke. In return, your application receives a reference to the server program and can treat the reference as if it were the server program itself.

The RDS object model embodies this functionality with the RDS.DataSpace object.

The server program is specified with a program identifier, or ProgID. The server uses the ProgID and the server machine's registry to locate information about the actual program to initiate.

RDS makes a distinction internally depending on whether the server program is on a remote server across the Internet or an intranet; a server on a local area network; or not on a server at all, but instead on a local dynamic-link library (DLL). This distinction determines how information is exchanged between the client and the server, and makes a tangible difference in the type of reference returned to your client application. However, from your point of view, this distinction has no special meaning. All that matters is that you receive a usable program reference.

RDSServer.DataFactory

RDS provides a default server program that can either perform a SQL query against the data source and return a Recordset object, or take a Recordset object and update the data source.

The RDS object model embodies this functionality with the RDSServer.DataFactory object.

In addition, this object has a method for creating an empty Recordset object that you can fill programmatically, and another method for converting a Recordset object into a text string to build a Web page.

With ADO 2.0, you can override some of the standard connection and command behavior of the RDSServer.DataFactory with a DataFactory handler and a customization file that contains connection, command, and security parameters.

The server program is sometimes called a business object. You can write your own custom business object that can perform complicated data access, validity checks, and so on. Even when writing a custom business object, you can create an instance of an RDSServer.DataFactory object and use some of its methods to accomplish your own tasks.

RDS.DataControl

RDS provides a means to combine the functionality of the RDS.DataSpace and RDSServer.DataFactory, and also enable visual controls to easily use the Recordset object returned by a query from a data source. RDS attempts, for the most common case, to do as much as possible to automatically gain access to information on a server and display it in a visual control.

The RDS object model embodies this functionality with the RDS.DataControl object.

The RDS.DataControl has two aspects. One aspect pertains to the data source. If you set the command and connection properties of the RDS.DataControl, it will automatically use the RDS.DataSpace to create a reference to the default RDSServer.DataFactory object. Then the RDSServer.DataFactory will use the connection property value to connect to the data source, use the command property value to obtain a Recordset from the data source, then return the Recordset object to the RDS.DataControl.

The second aspect pertains to the display of returned Recordset information in a visual control. You can associate a visual control with the RDS.DataControl (in a process called binding) and gain access to the information in the associated Recordset object, displaying query results on a Web page in Internet Explorer. Each RDS.DataControl object binds one Recordset object, representing the results of a single query, to one or more visual controls (for example, a text box, combo box, grid control, and so forth). There may be more than one RDS.DataControl object on each page. Each RDS.DataControl object can be connected to a different data source and contain the results of a separate query.

The RDS.DataControl object also has its own methods for navigating, sorting, and filtering the rows of the associated Recordset object. These methods are similar, but not the same as the methods on the ADO Recordset object.

Events

RDS supports two of its own events, which are independent of the ADO Event Model. The onReadyStateChange event is called whenever the RDS.DataControl ReadyState property changes, thus notifying you when an asynchronous operation has completed, terminated, or experienced an error. The onError event is called whenever an error occurs, even if the error occurs during an asynchronous operation.

Note The Microsoft Internet Explorer environment provides two additional events to RDS—onDataSetChanged and onDataSetComplete.

Next … RDS Programming Model with Objects.


RDS Programming Model with Objects

The goal of RDS is to gain access to and update data sources through an intermediary like the Internet Information Server. The programming model specifies the sequence of activities necessary to accomplish this goal. The object model specifies the objects whose methods and properties affect the programming model.

RDS provides the means to perform the following sequence of actions:

  1. Specify the program to be invoked on the server, and obtain a way (proxy) to refer to it from the client. (RDS.DataSpace)

  2. Invoke the server program. Pass parameters to the server program that identify the data source and the command to issue. (proxy or RDS.DataControl)

  3. The server program obtains a Recordset object from the data source, typically by using ADO. Optionally, the Recordset object is processed on the server. (RDSServer.DataFactory)

  4. The server program returns the final Recordset object to the client application. (proxy)

  5. On the client, the Recordset object is put into a form that can be easily used by visual controls. (visual control and RDS.DataControl)

  6. Changes to the Recordset object are sent back to the server and used to update the data source. (RDS.DataControl or RDSServer.DataFactory)

Next … The RDS Object Model Summary.


The RDS Object Model Summary

Object | Description
RDS.DataSpace | This object only contains a method to obtain a server proxy. The proxy may be the default or a custom server program (business object). The server program may be invoked on the Internet, an intranet, or local area network, or be a local dynamic-link library.
RDSServer.DataFactory | This object represents the default server program. It executes the default RDS data retrieval and update behavior.
RDS.DataControl
  • This object can automatically invoke the RDS.DataSpace and RDSServer.DataFactory objects.

  • Use this object to invoke the default RDS data retrieval or update behavior.

  • This object also provides the means for visual controls to access the returned Recordset object.


ADO Object Model

Each of the Connection, Command, Recordset, and Field objects also has a Properties collection.


Command Object (ADO)

A Command object is a definition of a specific command that you intend to execute against a data source.

Remarks

Use a Command object to query a database and return records in a Recordset object, to execute a bulk operation, or to manipulate the structure of a database. Depending on the functionality of the provider, some Command collections, methods, or properties may generate an error when referenced.

With the collections, methods, and properties of a Command object, you can do the following:

  • Define the executable text of the command (for example, an SQL statement) with the CommandText property.

  • Define parameterized queries or stored-procedure arguments with Parameter objects and the Parameters collection.

  • Execute a command and return a Recordset object if appropriate with the Execute method.

  • Specify the type of command with the CommandType property prior to execution to optimize performance.

  • Control whether or not the provider saves a prepared (or compiled) version of the command prior to execution with the Prepared property.

  • Set the number of seconds a provider will wait for a command to execute with the CommandTimeout property.

  • Associate an open connection with a Command object by setting its ActiveConnection property.

  • Set the Name property to identify the Command object as a method on the associated Connection object.

  • Pass a Command object to the Source property of a Recordset in order to obtain data.

Note To execute a query without using a Command object, pass a query string to the Execute method of a Connection object or to the Open method of a Recordset object. However, a Command object is required when you want to persist the command text and re-execute it, or use query parameters.

To create a Command object independently of a previously defined Connection object, set its ActiveConnection property to a valid connection string. ADO still creates a Connection object, but it doesn't assign that object to an object variable. However, if you are associating multiple Command objects with the same connection, you should explicitly create and open a Connection object; this assigns the Connection object to an object variable. If you do not set the Command objects' ActiveConnection property to this object variable, ADO creates a new Connection object for each Command object, even if you use the same connection string.

To execute a Command, simply call it by its Name property on the associated Connection object. The Command must have its ActiveConnection property set to the Connection object. If the Command has parameters, pass values for them as arguments to the method.


Connection Object (ADO)

A Connection object represents an open connection to a data source.

Remarks

A Connection object represents a unique session with a data source. In the case of a client/server database system, it may be equivalent to an actual network connection to the server. Depending on the functionality supported by the provider, some collections, methods, or properties of a Connection object may not be available.

Using the collections, methods, and properties of a Connection object, you can do the following:

  • Configure the connection before opening it with the ConnectionString, ConnectionTimeout, and Mode properties.

  • Set the CursorLocation property to invoke the Client Cursor Provider, which supports batch updates.

  • Set the default database for the connection with the DefaultDatabase property.

  • Set the level of isolation for the transactions opened on the connection with the IsolationLevel property.

  • Specify an OLE DB provider with the Provider property.

  • Establish, and later break, the physical connection to the data source with the Open and Close methods.

  • Execute a command on the connection with the Execute method and configure the execution with the CommandTimeout property.

  • Manage transactions on the open connection, including nested transactions if the provider supports them, with the BeginTrans, CommitTrans, and RollbackTrans methods and the Attributes property.

  • Examine errors returned from the data source with the Errors collection.

  • Read the version from the ADO implementation in use with the Version property.

  • Obtain schema information about your database with the OpenSchema method.

Note To execute a query without using a Command object, pass a query string to the Execute method of a Connection object. However, a Command object is required when you want to persist the command text and re-execute it, or use query parameters.

You can create Connection objects independently of any other previously defined object.

Note You can execute commands or stored procedures as if they were native methods on the Connection object.

To execute a command, give the command a name using the Command object Name property. Set the Command object’s ActiveConnection property to the connection. Then issue a statement where the command name is used as if it were a method on the Connection object, followed by any parameters, followed by a Recordset object if any rows are returned. Set the Recordset properties to customize the resulting recordset. For example:

Dim cnn As New ADODB.Connection
Dim cmd As New ADODB.Command
Dim rst As New ADODB.Recordset
...
cnn.Open "..."
cmd.Name = "yourCommandName"
cmd.ActiveConnection = cnn
...
'Your command name, any parameters, and an optional Recordset.
cnn.yourCommandName "parameter", rst

To execute a stored procedure, issue a statement where the stored procedure name is used as if it were a method on the Connection object, followed by any parameters. ADO will make a "best guess" of parameter types. For example:

Dim cnn As New ADODB.Connection
...
'Your stored procedure name and any parameters.
cnn.sp_yourStoredProcedureName "parameter"


Error Object (ADO)

An Error object contains details about data access errors pertaining to a single operation involving the provider.

Remarks

Any operation involving ADO objects can generate one or more provider errors. As each error occurs, one or more Error objects are placed in the Errors collection of the Connection object. When another ADO operation generates an error, the Errors collection is cleared, and the new set of Error objects is placed in the Errors collection.

Note Each Error object represents a specific provider error, not an ADO error. ADO errors are exposed to the run-time exception-handling mechanism. For example, in Microsoft Visual Basic, the occurrence of an ADO-specific error will trigger an On Error event and appear in the Err object. For a complete list of ADO errors, see the ADO Error Codes topic.

You can read an Error object’s properties to obtain specific details about each error, including the following:

  • The Description property, which contains the text of the error.

  • The Number property, which contains the Long integer value of the error constant.

  • The Source property, which identifies the object that raised the error. This is particularly useful when you have several Error objects in the Errors collection following a request to a data source.

  • The SQLState and NativeError properties, which provide information from SQL data sources.

When a provider error occurs, it is placed in the Errors collection of the Connection object. ADO supports the return of multiple errors by a single ADO operation to allow for error information specific to the provider. To obtain this rich error information in an error handler, use the appropriate error-trapping features of the language or environment you are working with, then use nested loops to enumerate the properties of each Error object in the Errors collection.

Microsoft Visual Basic and VBScript If there is no valid Connection object, you will need to retrieve error information from the Err object.

Just as providers do, ADO clears the OLE Error Info object before making a call that could potentially generate a new provider error. However, the Errors collection on the Connection object is cleared and populated only when the provider generates a new error, or when the Clear method is called.

Some properties and methods return warnings that appear as Error objects in the Errors collection but do not halt a program's execution. Before you call the Resync, UpdateBatch, or CancelBatch methods on a Recordset object, the Open method on a Connection object, or set the Filter property on a Recordset object, call the Clear method on the Errors collection so that you can read the Count property of the Errors collection to test for returned warnings.


Field Object (ADO)

A Field object represents a column of data with a common data type.

Remarks

A Recordset object has a Fields collection made up of Field objects. Each Field object corresponds to a column in the Recordset. You use the Value property of Field objects to set or return data for the current record. Depending on the functionality the provider exposes, some collections, methods, or properties of a Field object may not be available.

With the collections, methods, and properties of a Field object, you can do the following:

  • Return the name of a field with the Name property.

  • View or change the data in the field with the Value property.

  • Return the basic characteristics of a field with the Type, Precision, and NumericScale properties.

  • Return the declared size of a field with the DefinedSize property.

  • Return the actual size of the data in a given field with the ActualSize property.

  • Determine what types of functionality are supported for a given field with the Attributes property and Properties collection.

  • Manipulate the values of fields containing long binary or long character data with the AppendChunk and GetChunk methods.

  • If the provider supports batch updates, resolve discrepancies in field values during batch updating with the OriginalValue and UnderlyingValue properties.

All of the metadata properties (Name, Type, DefinedSize, Precision, and NumericScale) are available before opening the Field object’s Recordset. Setting them at that time is useful for dynamically constructing forms.


Parameter Object (ADO)

A Parameter object represents a parameter or argument associated with a Command object based on a parameterized query or stored procedure.

Remarks

Many providers support parameterized commands. These are commands where the desired action is defined once, but variables (or parameters) are used to alter some details of the command. For example, an SQL SELECT statement could use a parameter to define the matching criteria of a WHERE clause, and another to define the column name for a SORT BY clause.

Parameter objects represent parameters associated with parameterized queries, or the in/out arguments and the return values of stored procedures. Depending on the functionality of the provider, some collections, methods, or properties of a Parameter object may not be available.

With the collections, methods, and properties of a Parameter object, you can do the following:

  • Set or return the name of a parameter with the Name property.

  • Set or return the value of a parameter with the Value property.

  • Set or return parameter characteristics with the Attributes and Direction, Precision, NumericScale, Size, and Type properties.

  • Pass long binary or character data to a parameter with the AppendChunk method.

If you know the names and properties of the parameters associated with the stored procedure or parameterized query you wish to call, you can use the CreateParameter method to create Parameter objects with the appropriate property settings and use the Append method to add them to the Parameters collection. This lets you set and return parameter values without having to call the Refresh method on the Parameters collection to retrieve the parameter information from the provider, a potentially resource-intensive operation.


Property Object (ADO)

A Property object represents a dynamic characteristic of an ADO object that is defined by the provider.

Remarks

ADO objects have two types of properties: built-in and dynamic.

Built-in properties are those properties implemented in ADO and immediately available to any new object, using the MyObject.Property syntax. They do not appear as Property objects in an object’s Properties collection, so although you can change their values, you cannot modify their characteristics.

Dynamic properties are defined by the underlying data provider, and appear in the Properties collection for the appropriate ADO object. For example, a property specific to the provider may indicate if a Recordset object supports transactions or updating. These additional properties will appear as Property objects in that Recordset object’s Properties collection. Dynamic properties can be referenced only through the collection, using the MyObject.Properties(0) or MyObject.Properties("Name") syntax.

You cannot delete either kind of property.

A dynamic Property object has four built-in properties of its own:

  • The Name property is a string that identifies the property.

  • The Type property is an integer that specifies the property data type.

  • The Value property is a variant that contains the property setting.

  • The Attributes property is a long value that indicates characteristics of the property specific to the provider.


RDS.DataControl Object

The RDS.DataControl object binds a data query Recordset to one or more controls (for example, a text box, grid control, or combo box) to display the ADOR.Recordset data on a Web page.

Syntax

<OBJECT CLASSID="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33" ID="DataControl"

<PARAM NAME="Connect" VALUE="DSN=DSNName;UID=usr;PWD=pw;">

<PARAM NAME="Server" VALUE="http://awebsrvr">

<PARAM NAME="SQL" VALUE="QueryText">

</OBJECT>

Remarks

The class ID for the RDS.DataControl object is BD96C556-65A3-11D0-983A-00C04FC29E33.

For a basic scenario, you need to set only the SQL, Connect, and Server properties of the RDS.DataControl object, which will automatically call the default business object, RDSServer.DataFactory.

All the properties in the RDS.DataControl are optional because custom business objects can replace their functionality.

Use one RDS.DataControl object to link the results of a single query to one or more visual controls. For example, suppose you code a query that requests customer data such as Name, Residence, Place of Birth, Age, and Priority Customer Status. You can use a single RDS.DataControl object to display a customer's Name, Age, and Region in three separate text boxes, Priority Customer Status in a check box, and all the data in a grid control.

Use different RDS.DataControl objects to link the results of multiple queries to different visual controls. For example, suppose you use one query to obtain information about a customer, and a second query to obtain information about merchandise the customer has purchased. You want to display the results of the first query in three text boxes and one check box, and the results of the second query in a grid control. If you use the default business object (RDSServer.DataFactory), you need to do the following:

  • Add two RDS.DataControl objects to your Web page.

  • Write two queries, one for each SQL property of the two RDS.DataControl objects. One RDS.DataControl object will contain a SQL query requesting customer information; the second will contain a query requesting a list of merchandise the customer has purchased.

  • In each of the bound controls’ OBJECT tags, specify the DATAFLD value to set the values for the data you want to display in each visual control.

There is no count restriction on the number of RDS.DataControl objects that you can embed via OBJECT tags on a single Web page.

When you define the RDS.DataControl object on a Web page, use nonzero Height and Width values such as 1 (to avoid the inclusion of extra space).

Remote Data Service client components are already included as part of the Internet Explorer 4.0 installation; therefore, you don't need to include a CODEBASE parameter in your RDS.DataControl object tag.

Tested Controls

The following table lists the data-aware controls that have been tested to work with the RDS.DataControl object and associated client-side components. Other controls may also work with Remote Data Service, but they have not been tested.

Control name | File name | Class ID (CLSID)
SSDBGrid | SSDATB32.ocx (Sheridan) | AC05DC80-7DF1-11d0-839E-00A024A94B3A

With Internet Explorer 4.0, you can bind to data by using HTML controls and ActiveX® controls only if they are marked as apartment model controls.

The controls listed are not distributed with Remote Data Service, but may be purchased as part of Microsoft® Visual Basic®, Enterprise Edition or from Sheridan Systems, Inc.

Important You may not redistribute the ActiveX controls that are deployed as a part of Remote Data Service samples in any way. They are provided as part of the sample applications and may not be redistributed to other parties under any circumstances.

Microsoft Visual Basic Users The RDS.DataControl is used only in Web-based applications. A Visual Basic client application has no need for it.


RDS.DataSpace Object

The RDS.DataSpace object creates client-side proxies to custom business objects located on the middle tier.

Remarks

Remote Data Service needs business object proxies so that client-side components can communicate with business objects located on the middle tier. Proxies facilitate the packaging, unpackaging, and transport (marshaling) of the application's recordset data across process or machine boundaries.

Remote Data Service uses the RDS.DataSpace object's CreateObject method to create business object proxies. The business object proxy is dynamically created whenever an instance of its middle-tier business object counterpart is created. Remote Data Service supports the following protocols: HTTP, HTTPS (HTTP Secure Sockets), DCOM, and in-process (client components and the business object reside on the same computer).

The class ID for the RDS.DataSpace object is BD96C556-65A3-11D0-983A-00C04FC29E36.


RDSServer.DataFactory Object

This default server-side business object implements methods that provide read/write data access to specified data sources for client-side applications.

Remarks

The RDSServer.DataFactory object is designed as a server-side Automation object that receives client requests. In an Internet implementation, it resides on a Web server and is instantiated by the ADISAPI component. The RDSServer.DataFactory object provides read and write access to specified data sources, but doesn't contain any validation or business rules logic.

If you use a method that is available in both the RDSServer.DataFactory and RDS.DataControl objects, Remote Data Service uses the RDS.DataControl version by default. The default assumes a basic programming scenario, where the RDSServer.DataFactory serves as a generic server-side business object.

If you want your Web application to handle task-specific server-side processing, you can replace the RDSServer.DataFactory with a custom business object.

You can create server-side business objects that call the RDSServer.DataFactory methods, such as Query and CreateRecordset. This is helpful if you want to add functionality to your business objects, but take advantage of existing Remote Data Service technologies.

The class ID for the RDSServer.DataFactory object is 9381D8F5-0288-11D0-9501-00AA00B911A5.


Recordset Object (ADO)

A Recordset object represents the entire set of records from a base table or the results of an executed command. At any time, the Recordset object refers to only a single record within the set as the current record.

Remarks

You use Recordset objects to manipulate data from a provider. When you use ADO, you manipulate data almost entirely using Recordset objects. All Recordset objects are constructed using records (rows) and fields (columns). Depending on the functionality supported by the provider, some Recordset methods or properties may not be available.

ADOR.Recordset and ADODB.Recordset are ProgIDs that you can use to create a Recordset object. The Recordset objects that result behave identically, regardless of the ProgID. The ADOR.Recordset is installed with Microsoft® Internet Explorer; the ADODB.Recordset is installed with ADO. The behavior of a Recordset object is affected by its environment (that is, client, server, Internet Explorer, and so on). Differences are noted in the Help topics for properties, methods, and events.

There are four different cursor types defined in ADO:

  • Dynamic cursor—allows you to view additions, changes, and deletions by other users, and allows all types of movement through the Recordset that don't rely on bookmarks; allows bookmarks if the provider supports them.

  • Keyset cursor—behaves like a dynamic cursor, except that it prevents you from seeing records that other users add, and prevents access to records that other users delete. Data changes by other users will still be visible. It always supports bookmarks and therefore allows all types of movement through the Recordset.

  • Static cursor—provides a static copy of a set of records for you to use to find data or generate reports; always allows bookmarks and therefore allows all types of movement through the Recordset. Additions, changes, or deletions by other users will not be visible. This is the only type of cursor allowed when you open a client-side (ADOR) Recordset object.

  • Forward-only cursor—behaves identically to a dynamic cursor except that it allows you to scroll only forward through records. This improves performance in situations where you need to make only a single pass through a Recordset.

Set the CursorType property prior to opening the Recordset to choose the cursor type, or pass a CursorType argument with the Open method. Some providers don’t support all cursor types. Check the documentation for the provider. If you don't specify a cursor type, ADO opens a forward-only cursor by default.

When used with some providers (such as the Microsoft ODBC Provider for OLE DB in conjunction with Microsoft SQL Server), you can create Recordset objects independently of a previously defined Connection object by passing a connection string with the Open method. ADO still creates a Connection object, but it doesn't assign that object to an object variable. However, if you are opening multiple Recordset objects over the same connection, you should explicitly create and open a Connection object; this assigns the Connection object to an object variable. If you do not use this object variable when opening your Recordset objects, ADO creates a new Connection object for each new Recordset, even if you pass the same connection string.

You can create as many Recordset objects as needed.

When you open a Recordset, the current record is positioned to the first record (if any) and the BOF and EOF properties are set to False. If there are no records, the BOF and EOF property settings are True.

You can use the MoveFirst, MoveLast, MoveNext, and MovePrevious methods, as well as the Move method, and the AbsolutePosition, AbsolutePage, and Filter properties to reposition the current record, assuming the provider supports the relevant functionality. Forward-only Recordset objects support only the MoveNext method. When you use the Move methods to visit each record (or enumerate the Recordset), you can use the BOF and EOF properties to see if you've moved beyond the beginning or end of the Recordset.

Recordset objects can support two types of updating: immediate and batched. In immediate updating, all changes to data are written immediately to the underlying data source once you call the Update method. You can also pass arrays of values as parameters with the AddNew and Update methods and simultaneously update several fields in a record.

If a provider supports batch updating, you can have the provider cache changes to more than one record and then transmit them in a single call to the database with the UpdateBatch method. This applies to changes made with the AddNew, Update, and Delete methods. After you call the UpdateBatch method, you can use the Status property to check for any data conflicts in order to resolve them.

Note To execute a query without using a Command object, pass a query string to the Open method of a Recordset object. However, a Command object is required when you want to persist the command text and re-execute it, or use query parameters.


Errors Collection (ADO)

The Errors collection contains all the Error objects created in response to a single failure involving the provider.

Remarks

Any operation involving ADO objects can generate one or more provider errors. As each error occurs, one or more Error objects can be placed in the Errors collection of the Connection object. When another ADO operation generates an error, the Errors collection is cleared, and the new set of Error objects can be placed in the Errors collection.

Each Error object represents a specific provider error, not an ADO error. ADO errors are exposed to the run-time exception-handling mechanism. For example, in Microsoft Visual Basic, the occurrence of an ADO-specific error will trigger an On Error event and appear in the Err object.

ADO operations that don't generate an error have no effect on the Errors collection. Use the Clear method to manually clear the Errors collection.

The set of Error objects in the Errors collection describes all errors that occurred in response to a single statement. Enumerating the specific errors in the Errors collection enables your error-handling routines to more precisely determine the cause and origin of an error, and take appropriate steps to recover.

Some properties and methods return warnings that appear as Error objects in the Errors collection but do not halt a program's execution. Before you call the Resync, UpdateBatch, or CancelBatch methods on a Recordset object, the Open method on a Connection object, or set the Filter property on a Recordset object, call the Clear method on the Errors collection so that you can read the Count property of the Errors collection to test for returned warnings.

Note See the Error object topic for a more detailed explanation of the way a single ADO operation can generate multiple errors.


Fields Collection (ADO)

A Fields collection contains all the Field objects of a Recordset object.

Remarks

A Recordset object has a Fields collection made up of Field objects. Each Field object corresponds to a column in the Recordset. You can populate the Fields collection before opening the Recordset by calling the Refresh method on the collection.

Note See the Field object topic for a more detailed explanation of how to use Field objects.


Parameters Collection (ADO)

A Parameters collection contains all the Parameter objects of a Command object.

Remarks

A Command object has a Parameters collection made up of Parameter objects.

Using the Refresh method on a Command object's Parameters collection retrieves provider parameter information for the stored procedure or parameterized query specified in the Command object. Some providers do not support stored procedure calls or parameterized queries; calling the Refresh method on the Parameters collection when using such a provider will return an error.

If you have not defined your own Parameter objects and you access the Parameters collection before calling the Refresh method, ADO will automatically call the method and populate the collection for you.

You can minimize calls to the provider to improve performance if you know the properties of the parameters associated with the stored procedure or parameterized query you wish to call. Use the CreateParameter method to create Parameter objects with the appropriate property settings and use the Append method to add them to the Parameters collection. This lets you set and return parameter values without having to call the provider for the parameter information. If you are writing to a provider that does not supply parameter information, you must manually populate the Parameters collection using this method to be able to use parameters at all. Use the Delete method to remove Parameter objects from the Parameters collection if necessary.


Properties Collection (ADO)

A Properties collection contains all the Property objects for a specific instance of an object.

Remarks

Some ADO objects have a Properties collection made up of Property objects. Each Property object corresponds to a characteristic of the ADO object specific to the provider.

Note See the Property Object topic for a more detailed explanation of how to use Property objects.


AddNew Method (ADO)

Creates a new record for an updatable Recordset object.

Syntax

recordset.AddNew FieldList, Values

Parameters

FieldList Optional. A single name or an array of names or ordinal positions of the fields in the new record.

Values Optional. A single value or an array of values for the fields in the new record. If Fields is an array, Values must also be an array with the same number of members; otherwise, an error occurs. The order of field names must match the order of field values in each array.

Remarks

Use the AddNew method to create and initialize a new record. Use the Supports method with adAddNew to verify whether you can add records to the current Recordset object.

After you call the AddNew method, the new record becomes the current record and remains current after you call the Update method. If the Recordset object does not support bookmarks, you may not be able to access the new record once you move to another record. Depending on your cursor type, you may need to call the Requery method to make the new record accessible.

If you call AddNew while editing the current record or while adding a new record, ADO calls the Update method to save any changes and then creates the new record.

The behavior of the AddNew method depends on the updating mode of the Recordset object and whether or not you pass the Fields and Values arguments.

In immediate update mode (the provider writes changes to the underlying data source once you call the Update method), calling the AddNew method without arguments sets the EditMode property to adEditAdd. The provider caches any field value changes locally. Calling the Update method posts the new record to the database and resets the EditMode property to adEditNone. If you pass the Fields and Values arguments, ADO immediately posts the new record to the database (no Update call is necessary); the EditMode property value does not change (adEditNone).

In batch update mode (the provider caches multiple changes and writes them to the underlying data source only when you call the UpdateBatch method), calling the AddNew method without arguments sets the EditMode property to adEditAdd. The provider caches any field value changes locally. Calling the Update method adds the new record to the current recordset and resets the EditMode property to adEditNone, but the provider does not post the changes to the underlying database until you call the UpdateBatch method. If you pass the Fields and Values arguments, ADO sends the new record to the provider for storage in a cache; you need to call the UpdateBatch method to post the new record to the underlying database.


Append Method (ADO)

Appends an object to a collection. If the collection is Fields, a new Field object may be created before it is appended to the collection.

Syntax

collection.Append object

fields.Append Name, Type, DefinedSize, Attrib

Parameters

collection A collection object.

fields A Fields collection.

object An object variable representing the object to be appended.

Name A String. The name of the new Field object, which must not be the same name as any other object in fields.

Type A DataTypeEnum, whose default value is adEmpty. The data type of the new field.

DefinedSize Optional. A Long. The defined size in characters or bytes of the new field. The default value for this parameter is derived from Type. (The default Type is adEmpty, and default DefinedSize is unspecified.)

Attrib Optional. A FieldAttributeEnum, whose default value is adFldDefault. Specifies attributes for the new field. If this value is not specified, the field will contain attributes derived from Type.

Parameter

Use the Append method on a collection to add an object to that collection. This method is available only on the Parameters collection of a Command object. You must set the Type property of a Parameter object before appending it to the Parameters collection. If you select a variable-length data type, you must also set the Size property to a value greater than zero.

By describing the parameter yourself, you can minimize calls to the provider and consequently improve performance when using stored procedures or parameterized queries. However, you must know the properties of the parameters associated with the stored procedure or parameterized query you want to call. Use the CreateParameter method to create Parameter objects with the appropriate property settings and use the Append method to add them to the Parameters collection. This lets you set and return parameter values without having to call the provider for the parameter information. If you are writing to a provider that does not supply parameter information, you must manually populate the Parameters collection using this method to be able to use parameters at all.

Fields

You must set the CursorLocation property to adUseClient before calling the fields.Append method.

Calling the fields.Append method for an open Recordset, or a Recordset where the ActiveConnection property has been set, will cause a run-time error.


AppendChunk Method (ADO)

Appends data to a large text or binary data Field or Parameter object.

Syntax

object.AppendChunk Data

Parameters

object A Field or Parameter object.

Data A Variant containing the data you want to append to the object.

Remarks

Use the AppendChunk method on a Field or Parameter object to fill it with long binary or character data. In situations where system memory is limited, you can use the AppendChunk method to manipulate long values in portions rather than in their entirety.

Field

If the adFldLong bit in the Attributes property of a Field object is set to true, you can use the AppendChunk method for that field.

The first AppendChunk call on a Field object writes data to the field, overwriting any existing data. Subsequent AppendChunk calls add to existing data. If you are appending data to one field and then you set or read the value of another field in the current record, ADO assumes that you are done appending data to the first field. If you call the AppendChunk method on the first field again, ADO interprets the call as a new AppendChunk operation and overwrites the existing data. Accessing fields in other Recordset objects that are not clones of the first Recordset object will not disrupt AppendChunk operations.

If there is no current record when you call AppendChunk on a Field object, an error occurs.

Parameter

If the adFldLong bit in the Attributes property of a Parameter object is set to true, you can use the AppendChunk method for that parameter.

The first AppendChunk call on a Parameter object writes data to the parameter, overwriting any existing data. Subsequent AppendChunk calls on a Parameter object add to existing parameter data. An AppendChunk call that passes a null value discards all of the parameter data.


BeginTrans, CommitTrans, and RollbackTrans Methods (ADO)

These transaction methods manage transaction processing within a Connection object as follows:

  • BeginTrans begins a new transaction.

  • CommitTrans saves any changes and ends the current transaction. It may also start a new transaction.

  • RollbackTrans cancels any changes made during the current transaction and ends the transaction. It may also start a new transaction.

Syntax

level = object.BeginTrans()

object.BeginTrans

object.CommitTrans

object.RollbackTrans

Return Value

BeginTrans can be called as a function that returns a Long variable indicating the nesting level of the transaction.

Parameters

object A Connection object.

Connection

Use these methods with a Connection object when you want to save or cancel a series of changes made to the source data as a single unit. For example, to transfer money between accounts, you subtract an amount from one and add the same amount to the other. If either update fails, the accounts no longer balance. Making these changes within an open transaction ensures that either all or none of the changes go through.

Note Not all providers support transactions. Verify that the provider-defined property "Transaction DDL" appears in the Connection object's Properties collection, indicating that the provider supports transactions. If the provider does not support transactions, calling one of these methods will return an error.

Once you call the BeginTrans method, the provider will no longer instantaneously commit any changes you make until you call CommitTrans or RollbackTrans to end the transaction.

For providers that support nested transactions, calling the BeginTrans method within an open transaction starts a new, nested transaction. The return value indicates the level of nesting: a return value of "1" indicates you have opened a top-level transaction (that is, the transaction is not nested within another transaction), "2" indicates that you have opened a second-level transaction (a transaction nested within a top-level transaction), and so forth. Calling CommitTrans or RollbackTrans affects only the most recently opened transaction; you must close or roll back the current transaction before you can resolve any higher-level transactions.

Calling the CommitTrans method saves changes made within an open transaction on the connection and ends the transaction. Calling the RollbackTrans method reverses any changes made within an open transaction and ends the transaction. Calling either method when there is no open transaction generates an error.

Depending on the Connection object's Attributes property, calling either the CommitTrans or RollbackTrans methods may automatically start a new transaction. If the Attributes property is set to adXactCommitRetaining, the provider automatically starts a new transaction after a CommitTrans call. If the Attributes property is set to adXactAbortRetaining, the provider automatically starts a new transaction after a RollbackTrans call.

Remote Data Service

The BeginTrans, CommitTrans, and RollbackTrans methods are not available on a client-side Connection object.


Cancel Method (ADO)

Cancels execution of a pending, asynchronous Execute or Open method call.

Syntax

object.Cancel

Remarks

Use the Cancel method to terminate execution of an asynchronous Execute or Open method call (that is, the method was invoked with the adConnectAsync, adExecuteAsync, or adFetchAsync option). Cancel will return a run-time error if adRunAsync was not used in the method you're trying to terminate.

The following table shows what task is terminated when you use the Cancel method on a particular type of object.

If object is a | The last asynchronous call to this method is terminated
Command | Execute
Connection | Execute or Open
Recordset | Open


Cancel Method (RDS)

Cancels the currently running asynchronous execution or fetch.

Syntax

RDS.DataControl.Cancel

Remarks

When you call Cancel, ReadyState is automatically set to adcReadyStateLoaded, and the Recordset will be empty.


CancelBatch Method (ADO)

Cancels a pending batch update.

Syntax

recordset.CancelBatch AffectRecords

Parameters

AffectRecords Optional. An AffectEnum value that determines how many records the CancelBatch method will affect. Can be one of the following constants:

Constant | Description
adAffectCurrent | Cancel pending updates only for the current record.
adAffectGroup | Cancel pending updates for records that satisfy the current Filter property setting. You must set the Filter property to one of the valid predefined constants in order to use this option.
adAffectAll | Default. Cancel pending updates for all the records in the Recordset object, including any hidden by the current Filter property setting.

Remarks

Use the CancelBatch method to cancel any pending updates in a recordset in batch update mode. If the recordset is in immediate update mode, calling CancelBatch without adAffectCurrent generates an error.

If you are editing the current record or are adding a new record when you call CancelBatch, ADO first calls the CancelUpdate method to cancel any cached changes; after that, all pending changes in the recordset are canceled.

It's possible that the current record will be indeterminable after a CancelBatch call, especially if you were in the process of adding a new record. For this reason, it is prudent to set the current record position to a known location in the recordset after the CancelBatch call. For example, call the MoveFirst method.

If the attempt to cancel the pending updates fails because of a conflict with the underlying data (for example, a record has been deleted by another user), the provider returns warnings to the Errors collection but does not halt program execution. A run-time error occurs only if there are conflicts on all the requested records. Use the Filter property (adFilterAffectedRecords) and the Status property to locate records with conflicts.


CancelUpdate Method (ADO)

Cancels any changes made to the current record or to a new record prior to calling the Update method.

Syntax

recordset.CancelUpdate

Remarks

Use the CancelUpdate method to cancel any changes made to the current record or to discard a newly added record. You cannot undo changes to the current record or to a new record after you call the Update method unless the changes are either part of a transaction that you can roll back with the RollbackTrans method or part of a batch update that you can cancel with the CancelBatch method.

If you are adding a new record when you call the CancelUpdate method, the record that was current prior to the AddNew call becomes the current record again.

If you have not changed the current record or added a new record, calling the CancelUpdate method generates an error.


CancelUpdate Method (RDS)

Discards all the pending changes associated with the specified Recordset object, thus restoring the values since the last Refresh method call.

Syntax

DataControl.CancelUpdate

Parameters

DataControl An object variable that represents an RDS.DataControl object.

Remarks

The Client Cursor Engine keeps both a copy of the original values and a cache of changes. When you call CancelUpdate, the cache of changes is reset to empty, and the bound controls are refreshed with the original data.


Clear Method (ADO)

Removes all of the objects in a collection.

Syntax

Errors.Clear

Remarks

Use the Clear method on the Errors collection to remove all existing Error objects from the collection. When an error occurs, ADO automatically clears the Errors collection and fills it with Error objects based on the new error.

Some properties and methods return warnings that appear as Error objects in the Errors collection but do not halt a program's execution. Before you call the Resync, UpdateBatch, or CancelBatch methods on a Recordset object, the Open method on a Connection object, or set the Filter property on a Recordset object, call the Clear method on the Errors collection so that you can read the Count property of the Errors collection to test for returned warnings.


Clone Method (ADO)

Creates a duplicate Recordset object from an existing Recordset object. Optionally, specifies that the clone be read-only.

Syntax

Set rstDuplicate = rstOriginal.Clone (LockType)

Return Value

Returns a Recordset object reference.

Parameters

rstDuplicate An object variable identifying the duplicate Recordset object you're creating.

rstOriginal An object variable identifying the Recordset object you want to duplicate.

LockType Optional. A LockTypeEnum value that specifies either the lock type of the original Recordset, or a read-only Recordset.

Constant | Description
adLockUnspecified | Default. The clone is created with the same lock type as the original.
adLockReadOnly | The clone is created as read-only.

Remarks

Use the Clone method to create multiple, duplicate Recordset objects, particularly if you want to be able to maintain more than one current record in a given set of records. Using the Clone method is more efficient than creating and opening a new Recordset object with the same definition as the original.

The current record of a newly created clone is set to the first record.

Changes you make to one Recordset object are visible in all of its clones regardless of cursor type. However, once you execute Requery on the original Recordset, the clones will no longer be synchronized to the original.

Closing the original Recordset does not close its copies; closing a copy does not close the original or any of the other copies.

You can only clone a Recordset object that supports bookmarks. Bookmark values are interchangeable; that is, a bookmark reference from one Recordset object refers to the same record in any of its clones.


Close Method (ADO)

Closes an open object and any dependent objects.

Syntax

object.Close

Remarks

Use the Close method to close either a Connection object or a Recordset object to free any associated system resources. Closing an object does not remove it from memory; you can change its property settings and open it again later. To completely eliminate an object from memory, set the object variable to Nothing.

Connection

Using the Close method to close a Connection object also closes any active Recordset objects associated with the connection. A Command object associated with the Connection object you are closing will persist, but it will no longer be associated with a Connection object; that is, its ActiveConnection property will be set to Nothing. Also, the Command object's Parameters collection will be cleared of any provider-defined parameters.

You can later call the Open method to re-establish the connection to the same or another data source. While the Connection object is closed, calling any methods that require an open connection to the data source generates an error.

Closing a Connection object while there are open Recordset objects on the connection rolls back any pending changes in all of the Recordset objects. Explicitly closing a Connection object (calling the Close method) while a transaction is in progress generates an error. If a Connection object falls out of scope while a transaction is in progress, ADO automatically rolls back the transaction.

Recordset

Using the Close method to close a Recordset object releases the associated data and any exclusive access you may have had to the data through this particular Recordset object. You can later call the Open method to reopen the Recordset with the same or modified attributes. While the Recordset object is closed, calling any methods that require a live cursor generates an error.

If an edit is in progress while in immediate update mode, calling the Close method generates an error; call the Update or CancelUpdate method first. If you close the Recordset object during batch updating, all changes since the last UpdateBatch call are lost.

If you use the Clone method to create copies of an open Recordset object, closing the original or a clone does not affect any of the other copies.


CompareBookmarks Method (ADO)

Compares two bookmarks and returns an indication of their relative values.

Syntax

result = recordset.CompareBookmarks(Bookmark1, Bookmark2) As CompareEnum

Return Value

Returns a value that indicates the relative row position of two records represented by their bookmarks. The following values can be returned.

Constant | Description
adCompareLessThan | The first bookmark is before the second.
adCompareEqual | The bookmarks are equal.
adCompareGreaterThan | The first bookmark is after the second.
adCompareNotEqual | The bookmarks are not equal and not ordered.
adCompareNotComparable | The bookmarks cannot be compared.

Parameters

Bookmark1 The bookmark of the first row.

Bookmark2 The bookmark of the second row.

Remarks

The bookmarks must apply to the same Recordset object, or a Recordset object and its clone. You cannot reliably compare bookmarks from different Recordset objects, even if they were created from the same source or command. Nor can you compare bookmarks for a Recordset object whose underlying provider does not support comparisons.

A bookmark uniquely identifies a row in a Recordset object. Use the current row's Bookmark property to obtain its bookmark.

An invalid or incorrectly formed bookmark will cause an error.


ConvertToString Method (RDS)

Converts a Recordset to a MIME string that represents the recordset data.

Syntax

DataFactory.ConvertToString(Recordset)

Parameters

DataFactory An object variable that represents an RDSServer.DataFactory object.

Recordset An object variable that represents a Recordset object.

Remarks

With .asp files, use ConvertToString to embed the Recordset on an HTML page generated on the server to transport it to a client computer.

ConvertToString first loads the Recordset into Client Cursor Engine tables, and then generates a stream in MIME format.

On the client, Remote Data Service can convert the MIME string back into a fully functioning Recordset. It works well for handling fewer than 400 rows of data with no more than 1024 bytes width per row. You shouldn't use it for streaming BLOB data and large result sets over HTTP. No wire compression is performed on the string, so very large data sets will take considerable time to transport over HTTP when compared to the wire-optimized tablegram format defined and deployed by Remote Data Service as its native transport protocol format.

Note If you are using Active Server Pages to embed the resulting MIME string in a client HTML page, be aware that versions of VBScript earlier than version 2.0 limit the string's size to 32K. If this limit is exceeded, an "Out of string space" error is returned. Keep the query scope relatively small when using MIME embedding via .asp files. To fix this, download the latest version of VBScript from http://www.microsoft.com/vbscript.


CreateObject Method (RDS)

Creates the proxy for the target business object and returns a pointer to it. The proxy packages and marshals data to the server-side stub for communications with the business object to send requests and data over the Internet. For in-process component objects, no proxies are used, so just a pointer to the object is provided.

Syntax

Remote Data Service supports the following protocols: HTTP, HTTPS (HTTP over Secure Socket Layer), DCOM, and in-process.

Protocol | Syntax
HTTP | Set object = DataSpace.CreateObject("ProgId", "http://awebsrvr")
HTTPS | Set object = DataSpace.CreateObject("ProgId", "https://awebsrvr")
DCOM | Set object = DataSpace.CreateObject("ProgId", "machinename")
In-process | Set object = DataSpace.CreateObject("ProgId", "")

Parameters

Object An object variable that evaluates to an object that is the type specified in ProgID.

DataSpace An object variable that represents an RDS.DataSpace object used to create an instance of the new object.

ProgID A String that is the programmatic ID that identifies a server-side business object that implements your application's business rules.

awebsrvr or machinename A String that represents a URL identifying the Internet Information Server (IIS) Web server where an instance of the server business object is created.

Remarks

The HTTP protocol is the standard Web protocol; HTTPS is a secure Web protocol. Use the DCOM protocol when running a local-area network without HTTP. The in-process protocol is a local dynamic-link library (DLL); it does not use a network.


CreateParameter Method (ADO)

Creates a new Parameter object with the specified properties.

Syntax

Set parameter = command.CreateParameter (Name, Type, Direction, Size, Value)

Return Value

Returns a Parameter object.

Parameters

Name Optional. A String representing the name of the Parameter object.

Type Optional. A Long value specifying the data type of the Parameter object. See the Type property for valid settings.

Direction Optional. A Long value specifying the type of Parameter object. See the Direction property for valid settings.

Size Optional. A Long value specifying the maximum length for the parameter value in characters or bytes.

Value Optional. A Variant specifying the value for the Parameter object.

Remarks

Use the CreateParameter method to create a new Parameter object with the specified name, type, direction, size, and value. Any values you pass in the arguments are written to the corresponding Parameter properties.

This method does not automatically append the Parameter object to the Parameters collection of a Command object. This lets you set additional properties whose values ADO will validate when you append the Parameter object to the collection.

If you specify a variable-length data type in the Type argument, you must either pass a Size argument or set the Size property of the Parameter object before appending it to the Parameters collection; otherwise, an error occurs.


CreateRecordset Method (RDS)

Creates an empty, disconnected Recordset.

Syntax

object.CreateRecordset(ColumnInfos)

Parameters

Object An object variable that represents an RDSServer.DataFactory or RDS.DataControl object.

ColumnsInfos A Variant array of arrays defining each column in the Recordset being created. Each column definition contains an array of four required attributes.

Attribute | Description
Name | Name of the column header.
Type | Integer of data type.
Size | Integer of width in characters, regardless of data type.
Nullability | Boolean value.

The set of column arrays is then grouped into an array, which defines the Recordset.

Remarks

The server-side business object can populate the resulting ADODB.Recordset with data from a non-OLE DB data provider, such as an operating system file containing stock quotes.

The following table lists the data types supported by the RDSServer.DataFactory object's CreateRecordset method. The number listed is the reference number used to define fields.

Each of the data types is either fixed length or variable length. Fixed-length types should be defined with a size of –1, because the size is predetermined and a size definition is still required. Variable-length data types allow a size from 1 to 32767.

For some of the variable data types, the type may be coerced to the type noted in the Substitution column. You won't see the substitutions until after the Recordset is created and filled. Then you can check for the actual data type, if necessary.

Length | Constant | Number | Substitution
Fixed | adTinyInt | 16 |
Fixed | adSmallInt | 2 |
Fixed | adInteger | 3 |
Fixed | adBigInt | 20 |
Fixed | adUnsignedTinyInt | 17 |
Fixed | adUnsignedSmallInt | 18 |
Fixed | adUnsignedInt | 19 |
Fixed | adUnsignedBigInt | 21 |
Fixed | adSingle | 4 |
Fixed | adDouble | 5 |
Fixed | adCurrency | 6 |
Fixed | adDecimal | 14 |
Fixed | adNumeric | 131 |
Fixed | adBoolean | 11 |
Fixed | adError | 10 |
Fixed | adGuid | 72 |
Fixed | adDate | 7 |
Fixed | adDBDate | 133 |
Fixed | adDBTime | 134 |
Fixed | adDBTimestamp | 135 | 7
Variable | adBSTR | 8 | 130
Variable | adChar | 129 | 200
Variable | adVarChar | 200 |
Variable | adLongVarChar | 201 | 200
Variable | adWChar | 130 |
Variable | adVarWChar | 202 | 130
Variable | adLongVarWChar | 203 | 130
Variable | adBinary | 128 |
Variable | adVarBinary | 204 |
Variable | adLongVarBinary | 205 | 204


Delete Method (ADO Fields Collection)

Deletes an object from the Fields collection.

Syntax

Fields.Delete Field

Parameters

Field A Variant designating the Field object to delete. This parameter must be the name of the Field object; it cannot be an ordinal position or the Field object itself.

Remarks

Calling the Fields.Delete method on an open Recordset causes a run-time error.


Delete Method (ADO Parameters Collection)

Deletes an object from the Parameters collection.

Syntax

Parameters.Delete Index

Parameters

Index A String representing the name of the object you want to delete, or the object’s ordinal position (index) in the collection.

Remarks

Using the Delete method on a collection lets you remove one of the objects in the collection. This method is available only on the Parameters collection of a Command object. You must use the Parameter object's Name property or its collection index when calling the Delete method—an object variable is not a valid argument.


Delete Method (ADO Recordset)

Deletes the current record or a group of records.

Syntax

recordset.Delete AffectRecords

Parameters

AffectRecords An AffectEnum value that determines how many records the Delete method will affect. Can be one of the following constants.

Constant | Description
adAffectCurrent | Default. Delete only the current record.
adAffectGroup | Delete the records that satisfy the current Filter property setting. You must set the Filter property to one of the valid predefined constants in order to use this option.

Remarks

Using the Delete method marks the current record or a group of records in a Recordset object for deletion. If the Recordset object doesn't allow record deletion, an error occurs. If you are in immediate update mode, deletions occur in the database immediately. Otherwise, the records are marked for deletion from the cache and the actual deletion happens when you call the UpdateBatch method. (Use the Filter property to view the deleted records.)

Retrieving field values from the deleted record generates an error. After deleting the current record, the deleted record remains current until you move to a different record. Once you move away from the deleted record, it is no longer accessible.

If you nest deletions in a transaction, you can recover deleted records with the RollbackTrans method. If you are in batch update mode, you can cancel a pending deletion or group of pending deletions with the CancelBatch method.

If the attempt to delete records fails because of a conflict with the underlying data (for example, a record has already been deleted by another user), the provider returns warnings to the Errors collection but does not halt program execution. A run-time error occurs only if there are conflicts on all the requested records.


Execute Method (ADO Command)

Executes the query, SQL statement, or stored procedure specified in the CommandText property.

Syntax

For a row-returning Command:

Set recordset = command.Execute( RecordsAffected, Parameters, Options )

For a non–row-returning Command:

command.Execute RecordsAffected, Parameters, Options

Return Value

Returns a Recordset object reference.

Parameters

RecordsAffected Optional. A Long variable to which the provider returns the number of records that the operation affected.

Parameters Optional. A Variant array of parameter values passed with an SQL statement. (Output parameters will not return correct values when passed in this argument.)

Options Optional. A Long value that indicates how the provider should evaluate the CommandText property of the Command object. Can be any of the following:

Constant | Description
adCmdText | Indicates that the provider should evaluate CommandText as a textual definition of a command, such as an SQL statement.
adCmdTable | Indicates that ADO should generate an SQL query to return all rows from the table named in CommandText.
adCmdTableDirect | Indicates that the provider should return all rows from the table named in CommandText.
adCmdStoredProc | Indicates that the provider should evaluate CommandText as a stored procedure.
adCmdUnknown | Indicates that the type of command in CommandText is not known.
adExecuteAsync | Indicates that the command should execute asynchronously.
adFetchAsync | Indicates that the remaining rows after the initial quantity specified in the CacheSize property should be fetched asynchronously.

See the CommandType property for a more detailed explanation of the first four constants in this list.

Remarks

Using the Execute method on a Command object executes the query specified in the CommandText property of the object. If the CommandText property specifies a row-returning query, any results the execution generates are stored in a new Recordset object. If the command is not a row-returning query, the provider returns a closed Recordset object. Some application languages allow you to ignore this return value if no Recordset is desired.

If the query has parameters, the current values for the Command object's parameters are used unless you override these with parameter values passed with the Execute call. You can override a subset of the parameters by omitting new values for some of the parameters when calling the Execute method. The order in which you specify the parameters is the same order in which the method passes them. For example, if there were four (or more) parameters and you wanted to pass new values for only the first and fourth parameters, you would pass Array(var1,,,var4) as the Parameters argument.

Note Output parameters will not return correct values when passed in the Parameters argument.

An ExecuteComplete event will be issued when this operation concludes.


Execute Method (ADO Connection)

Executes the specified query, SQL statement, stored procedure, or provider-specific text.

Syntax

For a non–row-returning command string:

connection.Execute CommandText, RecordsAffected, Options

For a row-returning command string:

Set recordset = connection.Execute (CommandText, RecordsAffected, Options)

Return Value

Returns a Recordset object reference.

Parameters

CommandText A String containing the SQL statement, table name, stored procedure, or provider-specific text to execute.

RecordsAffected Optional. A Long variable to which the provider returns the number of records that the operation affected.

Options Optional. A Long value that indicates how the provider should evaluate the CommandText argument. Can be one of the following values.

Constant | Description
adCmdText | Indicates that the provider should evaluate CommandText as a textual definition of a command.
adCmdTable | Indicates that ADO should generate an SQL query to return all rows from the table named in CommandText.
adCmdTableDirect | Indicates that the provider should return all rows from the table named in CommandText.
adCmdTable | Indicates that the provider should evaluate CommandText as a table name.
adCmdStoredProc | Indicates that the provider should evaluate CommandText as a stored procedure.
adCmdUnknown | Indicates that the type of command in the CommandText argument is not known.
adExecuteAsync | Indicates that the command should execute asynchronously.
adFetchAsync | Indicates that the remaining rows after the initial quantity specified in the CacheSize property should be fetched asynchronously.

See the CommandType property for a more detailed explanation of the first four constants in this list.

Remarks

Using the Execute method on a Connection object executes whatever query you pass to the method in the CommandText argument on the specified connection. If the CommandText argument specifies a row-returning query, any results the execution generates are stored in a new Recordset object. If the command is not a row-returning query, the provider returns a closed Recordset object.

The returned Recordset object is always a read-only, forward-only cursor. If you need a Recordset object with more functionality, first create a Recordset object with the desired property settings, then use the Recordset object’s Open method to execute the query and return the desired cursor type.

The contents of the CommandText argument are specific to the provider and can be standard SQL syntax or any special command format that the provider supports.

An ExecuteComplete event will be issued when this operation concludes.


Find Method (ADO)

Searches a Recordset for the record that satisfies the specified criteria. If the criteria is met, the recordset position is set on the found record; otherwise, the position is set on the end of the recordset.

Syntax

Find (criteria, SkipRows, searchDirection, start)

Parameters

criteria A String containing a statement that specifies the column name, comparison operator, and value to use in the search.

SkipRows An optional Long value, whose default value is zero, that specifies the offset from the current row or start bookmark to begin the search.

searchDirection An optional SearchDirectionEnum value that specifies whether the search should begin on the current row or the next available row in the direction of the search. Its value can be adSearchForward or adSearchBackward. The search stops at the start or end of the recordset, depending on the value of searchDirection.

start An optional Variant bookmark to use as the starting position for the search.

Remarks

The comparison operator in criteria may be ">" (greater than), "<" (less than), "=" (equal), or "like" (pattern matching).

The value in criteria may be a string, floating point number, or date. String values are delimited with single quotes (for example, "state = 'WA'"). Date values are delimited with "#" (number sign) marks (for example, "start_date > #7/22/97#").

If the comparison operator is "like", the string value may contain "*" (one or more occurrences of any character) or "_" (one occurrence of any character). (For example, "state like M_*" matches Maine and Massachusetts.)


GetChunk Method (ADO)

Returns all or a portion of the contents of a large text or binary data Field object.

Syntax

variable = field.GetChunk( Size )

Return Value

Returns a Variant.

Parameters

Size A Long expression equal to the number of bytes or characters you want to retrieve.

Remarks

Use the GetChunk method on a Field object to retrieve part or all of its long binary or character data. In situations where system memory is limited, you can use the GetChunk method to manipulate long values in portions rather than in their entirety.

The data that a GetChunk call returns is assigned to variable. If Size is greater than the remaining data, the GetChunk method returns only the remaining data without padding variable with empty spaces. If the field is empty, the GetChunk method returns Null.

Each subsequent GetChunk call retrieves data starting from where the previous GetChunk call left off. However, if you are retrieving data from one field and then you set or read the value of another field in the current record, ADO assumes you are done retrieving data from the first field. If you call the GetChunk method on the first field again, ADO interprets the call as a new GetChunk operation and starts reading from the beginning of the data. Accessing fields in other Recordset objects that are not clones of the first Recordset object will not disrupt GetChunk operations.

If the adFldLong bit in the Attributes property of a Field object is set to True, you can use the GetChunk method for that field.

If there is no current record when you use the GetChunk method on a Field object, error 3021 (no current record) occurs.


GetRows Method (ADO)

Retrieves multiple records of a Recordset object into an array.

Syntax

array = recordset.GetRows( Rows, Start, Fields )

Return Value

Returns a two-dimensional array.

Parameters

Rows Optional. A Long expression indicating the number of records to retrieve. Default is adGetRowsRest (-1).

Start Optional. A String or Variant that evaluates to the bookmark for the record from which the GetRows operation should begin. You can also use one of the following BookmarkEnum values.

Constant | Description
adBookmarkCurrent | Start at the current record.
adBookmarkFirst | Start at the first record.
adBookmarkLast | Start at the last record.

Fields Optional. A Variant representing a single field name or ordinal position or an array of field names or ordinal position numbers. ADO returns only the data in these fields.

Remarks

Use the GetRows method to copy records from a Recordset into a two-dimensional array. The first subscript identifies the field and the second identifies the record number. The array variable is automatically dimensioned to the correct size when the GetRows method returns the data.

If you do not specify a value for the Rows argument, the GetRows method automatically retrieves all the records in the Recordset object. If you request more records than are available, GetRows returns only the number of available records.

If the Recordset object supports bookmarks, you can specify at which record the GetRows method should begin retrieving data by passing the value of that record's Bookmark property.

If you want to restrict the fields the GetRows call returns, you can pass either a single field name/number or an array of field names/numbers in the Fields argument.

After you call GetRows, the next unread record becomes the current record, or the EOF property is set to True if there are no more records.


GetString Method (ADO Recordset)

Returns the Recordset as a string.

Syntax

Set Variant = recordset.GetString(StringFormat, NumRows, ColumnDelimiter, RowDelimiter, NullExpr)

Return Value

Returns the Recordset as a string-valued Variant (BSTR).

Parameters

StringFormat Specifies that the Recordset should be converted to the following format.

Constant | Description
adClipString | Rows are delimited by RowDelimiter, columns by ColumnDelimiter, and NULL values by NullExpr. These three parameters are valid only with adClipString.

NumRows Optional. The number of rows in the recordset to convert. If NumRows is not specified, or if it is greater than the total number of rows in the recordset, then all the rows in the recordset are converted.

ColumnDelimiter Optional. Delimiter used between columns if specified, otherwise the TAB character.

RowDelimiter Optional. Delimiter used between rows if specified, otherwise the CARRIAGE RETURN character.

NullExpr Optional. Expression used in place of a NULL value if specified, otherwise the empty string.

Remarks

Row data, but no schema data, is saved to the string. Therefore, a recordset cannot be reopened using this string.

This method is equivalent to the RDO GetClipString method.


Item Method (ADO)

Returns a specific member of a collection by name or ordinal number.

Syntax

Set object = collection.Item ( Index )

Return Value

Returns an object reference.

Parameters

Index A Variant that evaluates either to the name or to the ordinal number of an object in a collection.

Remarks

Use the Item method to return a specific object in a collection. If the method cannot find an object in the collection corresponding to the Index argument, an error occurs. Also, some collections don't support named objects; for these collections, you must use ordinal number references.

The Item method is the default method for all collections; therefore, the following syntax forms are interchangeable:

collection.Item (Index)

collection (Index)


Move Method (ADO)

Moves the position of the current record in a Recordset object.

Syntax

recordset.Move NumRecords, Start

Parameters

NumRecords A signed Long expression specifying the number of records the current record position moves.

Start Optional. A String or Variant that evaluates to a bookmark. You can also use one of the following BookmarkEnum values:

Constant | Description
adBookmarkCurrent | Default. Start at the current record.
adBookmarkFirst | Start at the first record.
adBookmarkLast | Start at the last record.

Remarks

The Move method is supported on all Recordset objects.

If the NumRecords argument is greater than zero, the current record position moves forward (toward the end of the recordset). If NumRecords is less than zero, the current record position moves backward (toward the beginning of the recordset).

If the Move call would move the current record position to a point before the first record, ADO sets the current record to the position before the first record in the recordset (BOF is True). An attempt to move backward when the BOF property is already True generates an error.

If the Move call would move the current record position to a point after the last record, ADO sets the current record to the position after the last record in the recordset (EOF is True). An attempt to move forward when the EOF property is already True generates an error.

Calling the Move method from an empty Recordset object generates an error.

If you pass the Start argument, the move is relative to the record with this bookmark, assuming the Recordset object supports bookmarks. If not specified, the move is relative to the current record.

If you are using the CacheSize property to locally cache records from the provider, passing a NumRecords argument that moves the current record position outside the current group of cached records forces ADO to retrieve a new group of records starting from the destination record. The CacheSize property determines the size of the newly retrieved group, and the destination record is the first record retrieved.

If the Recordset object is forward-only, a user can still pass a NumRecords argument less than zero as long as the destination is within the current set of cached records. If the Move call would move the current record position to a record before the first cached record, an error will occur. Thus, you can use a record cache that supports full scrolling over a provider that supports only forward scrolling. Because cached records are loaded into memory, you should avoid caching more records than is necessary. Even if a forward-only Recordset object supports backward moves in this way, calling the MovePrevious method on any forward-only Recordset object still generates an error.


MoveFirst, MoveLast, MoveNext, and MovePrevious Methods (ADO)

Moves to the first, last, next, or previous record in a specified Recordset object and makes that record the current record.

Syntax

recordset.{MoveFirst | MoveLast | MoveNext | MovePrevious}

Remarks

Use the MoveFirst method to move the current record position to the first record in the Recordset.

Use the MoveLast method to move the current record position to the last record in the Recordset. The Recordset object must support bookmarks or backward cursor movement; otherwise, the method call will generate an error.

Use the MoveNext method to move the current record position one record forward (toward the bottom of the Recordset). If the last record is the current record and you call the MoveNext method, ADO sets the current record to the position after the last record in the Recordset (EOF is True). An attempt to move forward when the EOF property is already True generates an error.

Use the MovePrevious method to move the current record position one record backward (toward the top of the recordset). The Recordset object must support bookmarks or backward cursor movement; otherwise, the method call will generate an error. If the first record is the current record and you call the MovePrevious method, ADO sets the current record to the position before the first record in the recordset (BOF is True). An attempt to move backward when the BOF property is already True generates an error. If the Recordset object does not support either bookmarks or backward cursor movement, the MovePrevious method will generate an error.

If the recordset is forward-only and you want to support both forward and backward scrolling, you can use the CacheSize property to create a record cache that will support backward cursor movement through the Move method. Because cached records are loaded into memory, you should avoid caching more records than is necessary. You can call the MoveFirst method in a forward-only Recordset object; doing so may cause the provider to re-execute the command that generated the Recordset object.


MoveFirst, MoveLast, MoveNext, MovePrevious Methods (RDS)

Moves to the first, last, next, or previous record in a displayed Recordset.

Syntax

DataControl.Recordset.{MoveFirst | MoveLast | MoveNext | MovePrevious}

Parameters

DataControl An object variable that represents an RDS.DataControl object.

Remarks

You can use the Move methods with the RDS.DataControl object to navigate through the data records in the data-bound controls on a Web page. For example, suppose you display a recordset in a grid by binding to an RDS.DataControl object. You can then include First, Last, Next, and Previous buttons that users can click to move to the first, last, next, or previous record in the displayed Recordset. You do this by calling the MoveFirst, MoveLast, MoveNext, and MovePrevious methods of the RDS.DataControl object in the onClick procedures for the First, Last, Next, and Previous buttons, respectively. The Address Book example shows how to do this.


NextRecordset Method (ADO)

Clears the current Recordset object and returns the next Recordset by advancing through a series of commands.

Syntax

Set recordset2 = recordset1.NextRecordset( RecordsAffected )

Return Value

Returns a Recordset object. In the syntax model, recordset1 and recordset2 can be the same Recordset object, or you can use separate objects.

Parameters

RecordsAffected Optional. A Long variable to which the provider returns the number of records that the current operation affected.

Remarks

Use the NextRecordset method to return the results of the next command in a compound command statement or of a stored procedure that returns multiple results. If you open a Recordset object based on a compound command statement (for example, "SELECT * FROM table1;SELECT * FROM table2") using the Execute method on a Command or the Open method on a Recordset, ADO executes only the first command and returns the results to recordset. To access the results of subsequent commands in the statement, call the NextRecordset method.

As long as there are additional results, the NextRecordset method will continue to return Recordset objects. If a row-returning command returns no records, the returned Recordset object will be empty; test for this case by verifying that the BOF and EOF properties are both True. If a non–row-returning command executes successfully, the returned Recordset object will be closed, which you can verify by testing the State property on the Recordset. When there are no more results, recordset will be set to Nothing.

If an edit is in progress while in immediate update mode, calling the NextRecordset method generates an error; call the Update or CancelUpdate method first.

If you need to pass parameters for more than one command in the compound statement by filling the Parameters collection or by passing an array with the original Open or Execute call, the parameters must be in the same order in the collection or array as their respective commands in the command series. You must finish reading all the results before reading output parameter values.

When you call the NextRecordset method, ADO executes only the next command in the statement. If you explicitly close the Recordset object before stepping through the entire command statement, ADO never executes the remaining commands.

Remote Data Service Usage The NextRecordset method is not available on a client-side Recordset object.


Open Method (ADO Connection)

Opens a connection to a data source.

Syntax

connection.Open ConnectionString, UserID, Password, OpenOptions

Parameters

ConnectionString Optional. A String containing connection information. See the ConnectionString property for details on valid settings.

UserID Optional. A String containing a user name to use when establishing the connection.

Password Optional. A String containing a password to use when establishing the connection.

OpenOptions Optional. A ConnectOptionEnum value. If set to adConnectAsync, the connection will be opened asynchronously. A ConnectComplete event will be issued when the connection is available.

Remarks

Using the Open method on a Connection object establishes the physical connection to a data source. After this method successfully completes, the connection is live and you can issue commands against it and process the results.

Use the optional ConnectionString argument to specify a connection string containing a series of argument = value statements separated by semicolons. The ConnectionString property automatically inherits the value used for the ConnectionString argument. Therefore, you can either set the ConnectionString property of the Connection object before opening it, or use the ConnectionString argument to set or override the current connection parameters during the Open method call.

If you pass user and password information both in the ConnectionString argument and in the optional UserID and Password arguments, the UserID and Password arguments will override the values specified in ConnectionString.

When you have concluded your operations over an open Connection, use the Close method to free any associated system resources. Closing an object does not remove it from memory; you can change its property settings and use the Open method to open it again later. To completely eliminate an object from memory, set the object variable to Nothing.

Remote Data Service Usage When used on a client-side Connection object, the Open method doesn’t actually establish a connection to the server until a Recordset is opened on the Connection object.


Open Method (ADO Recordset)

Opens a cursor.

Syntax

recordset.Open Source, ActiveConnection, CursorType, LockType, Options

Parameters

Source Optional. A Variant that evaluates to a valid Command object variable name, an SQL statement, a table name, a stored procedure call, or the file name of a persisted Recordset.

ActiveConnection Optional. Either a Variant that evaluates to a valid Connection object variable name, or a String containing ConnectionString parameters.

CursorType Optional. A CursorTypeEnum value that determines the type of cursor that the provider should use when opening the Recordset. Can be one of the following constants (see the CursorType property for definitions of these settings).

Constant | Description
adOpenForwardOnly | (Default) Opens a forward-only–type cursor.
adOpenKeyset | Opens a keyset-type cursor.
adOpenDynamic | Opens a dynamic-type cursor.
adOpenStatic | Opens a static-type cursor.

LockType Optional. A LockTypeEnum value that determines what type of locking (concurrency) the provider should use when opening the Recordset. Can be one of the following constants (see the LockType property for more information).

Constant | Description
adLockReadOnly | (Default) Read-only—you cannot alter the data.
adLockPessimistic | Pessimistic locking, record by record—the provider does what is necessary to ensure successful editing of the records, usually by locking records at the data source immediately upon editing.
adLockOptimistic | Optimistic locking, record by record—the provider uses optimistic locking, locking records only when you call the Update method.
adLockBatchOptimistic | Optimistic batch updates—required for batch update mode as opposed to immediate update mode.

Options Optional. A Long value that indicates how the provider should evaluate the Source argument if it represents something other than a Command object, or that the Recordset should be restored from a file where it was previously saved. Can be one of the following constants (see the CommandType property for a more detailed explanation of the first five constants in this list).

Constant | Description
adCmdText | Indicates that the provider should evaluate Source as a textual definition of a command.
adCmdTable | Indicates that ADO should generate an SQL query to return all rows from the table named in Source.
adCmdTableDirect | Indicates that the provider should return all rows from the table named in Source.
adCmdStoredProc | Indicates that the provider should evaluate Source as a stored procedure.
adCmdUnknown | Indicates that the type of command in the Source argument is not known.
adCommandFile | Indicates that the persisted (saved) Recordset should be restored from the file named in Source.
adExecuteAsync | Indicates that the Source should be executed asynchronously.
adFetchAsync | Indicates that after the initial quantity specified in the CacheSize property is fetched, any remaining rows should be fetched asynchronously.

Remarks

Using the Open method on a Recordset object opens a cursor that represents records from a base table, the results of a query, or a previously saved Recordset.

Use the optional Source argument to specify a data source using one of the following: a Command object variable, an SQL statement, a stored procedure, a table name, or a complete file path name.

The ActiveConnection argument corresponds to the ActiveConnection property and specifies in which connection to open the Recordset object. If you pass a connection definition for this argument, ADO opens a new connection using the specified parameters. You can change the value of this property after opening the Recordset to send updates to another provider. Or, you can set this property to Nothing (in Microsoft Visual Basic) to disconnect the Recordset from any provider.

For the other arguments that correspond directly to properties of a Recordset object (Source, CursorType, and LockType), the relationship of the arguments to the properties is as follows:

  • The property is read/write before the Recordset object is opened.

  • The property settings are used unless you pass the corresponding arguments when executing the Open method. If you pass an argument, it overrides the corresponding property setting, and the property setting is updated with the argument value.

  • After you open the Recordset object, these properties become read-only.

Note For Recordset objects whose Source property is set to a valid Command object, the ActiveConnection property is read-only, even if the Recordset object isn't open.

If you pass a Command object in the Source argument and also pass an ActiveConnection argument, an error occurs. The ActiveConnection property of the Command object must already be set to a valid Connection object or connection string.

If you pass something other than a Command object in the Source argument, you can use the Options argument to optimize evaluation of the Source argument. If the Options argument is not defined, you may experience diminished performance because ADO must make calls to the provider to determine if the argument is an SQL statement, a stored procedure, or a table name. If you know what Source type you're using, setting the Options argument instructs ADO to jump directly to the relevant code. If the Options argument does not match the Source type, an error occurs.

The default for the Options argument is adCommandFile if no connection is associated with the recordset. This will typically be the case for persisted Recordset objects.

If the data source returns no records, the provider sets both the BOF and EOF properties to True, and the current record position is undefined. You can still add new data to this empty Recordset object if the cursor type allows it.

When you have concluded your operations over an open Recordset object, use the Close method to free any associated system resources. Closing an object does not remove it from memory; you can change its property settings and use the Open method to open it again later. To completely eliminate an object from memory, set the object variable to Nothing.

Call Open with no operands, and before the ActiveConnection property is set, to create an instance of a Recordset created by appending fields to the Recordset Fields collection.


OpenSchema Method (ADO)

Obtains database schema information from the provider.

Syntax

Set recordset = connection.OpenSchema (QueryType, Criteria, SchemaID)

Return Values

Returns a Recordset object that contains schema information. The Recordset will be opened as a read-only, static cursor.

Parameters

QueryType The type of schema query to run. Can be any of the constants listed below.

Criteria Optional. An array of query constraints for each QueryType option, as listed below.

QueryType values | Criteria values
adSchemaAsserts | CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME
adSchemaCatalogs | CATALOG_NAME
adSchemaCharacterSets | CHARACTER_SET_CATALOG CHARACTER_SET_SCHEMA CHARACTER_SET_NAME
adSchemaCheckConstraints | CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME
adSchemaCollations | COLLATION_CATALOG COLLATION_SCHEMA COLLATION_NAME
adSchemaColumnDomainUsage | DOMAIN_CATALOG DOMAIN_SCHEMA DOMAIN_NAME COLUMN_NAME
adSchemaColumnPrivileges | TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME GRANTOR GRANTEE
adSchemaColumns | TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME
adSchemaConstraintColumnUsage | TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME
adSchemaConstraintTableUsage | TABLE_CATALOG TABLE_SCHEMA TABLE_NAME
adSchemaForeignKeys | PK_TABLE_CATALOG PK_TABLE_SCHEMA PK_TABLE_NAME FK_TABLE_CATALOG FK_TABLE_SCHEMA FK_TABLE_NAME
adSchemaIndexes | TABLE_CATALOG TABLE_SCHEMA INDEX_NAME TYPE TABLE_NAME
adSchemaKeyColumnUsage | CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME
adSchemaPrimaryKeys | PK_TABLE_CATALOG PK_TABLE_SCHEMA PK_TABLE_NAME
adSchemaProcedureColumns | PROCEDURE_CATALOG PROCEDURE_SCHEMA PROCEDURE_NAME COLUMN_NAME
adSchemaProcedureParameters | PROCEDURE_CATALOG PROCEDURE_SCHEMA PROCEDURE_NAME PARAMTER_NAME
adSchemaProcedures | PROCEDURE_CATALOG PROCEDURE_SCHEMA PROCEDURE_NAME PARAMTER_TYPE
adSchemaProviderSpecific | See Remarks
adSchemaProviderTypes | DATA_TYPE BEST_MATCH
adSchemaReferentialConstraints | CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME
adSchemaSchemata | CATALOG_NAME SCHEMA_NAME SCHEMA_OWNER
adSchemaSQLLanguages | <none>
adSchemaStatistics | TABLE_CATALOG TABLE_SCHEMA TABLE_NAME
adSchemaTableConstraints | CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE
adSchemaTablePrivileges | TABLE_CATALOG TABLE_SCHEMA TABLE_NAME GRANTOR GRANTEE
adSchemaTables | TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE
adSchemaTranslations | TRANSLATION_CATALOG TRANSLATION_SCHEMA TRANSLATION_NAME
adSchemaUsagePrivileges | OBJECT_CATALOG OBJECT_SCHEMA OBJECT_NAME OBJECT_TYPE GRANTOR GRANTEE
adSchemaViewColumnUsage | VIEW_CATALOG VIEW_SCHEMA VIEW_NAME
adSchemaViewTableUsage | VIEW_CATALOG VIEW_SCHEMA VIEW_NAME
adSchemaViews | TABLE_CATALOG TABLE_SCHEMA TABLE_NAME

SchemaID The GUID for a provider-schema schema query not defined by the OLE DB specification. This parameter is required if QueryType is set to adSchemaProviderSpecific; otherwise, it is not used.

Remarks

The OpenSchema method returns information about the data source, such as information about the tables on the server and the columns in the tables.

The Criteria argument is an array of values that can be used to limit the results of a schema query. Each schema query has a different set of parameters that it supports. The actual schemas are defined by the OLE DB specification under the IDBSchemaRowset interface. The ones supported in ADO are listed above.

The constant adSchemaProviderSpecific is used for the QueryType argument if the provider defines its own nonstandard schema queries outside those listed above. When this constant is used, the SchemaID argument is required to pass the GUID of the schema query to execute. If QueryType is set to adSchemaProviderSpecific but SchemaID is not provided, an error will result.

Providers are not required to support all of the OLE DB standard schema queries. Specifically, only adSchemaTables, adSchemaColumns, and adSchemaProviderTypes are required by the OLE DB specification. However, the provider is not required to support the Criteria constraints listed above for those schema queries.

Remote Data Service Usage The OpenSchema method is not available on a client-side Connection object.


Query Method (RDS)

Uses a valid SQL query string to return a Recordset.

Syntax

Set Recordset = DataFactory.Query Connection, Query

Parameters

Recordset An object variable that represents a Recordset object.

DataFactory An object variable that represents an RDSServer.DataFactory object.

Connection A String containing the server connection information. This is similar to the Connect property.

Query A String containing the SQL query.

Remarks

The query should use the SQL dialect of the database server. A result status is returned if there is an error with the query that was executed. The Query method doesn't perform any syntax checking on the Query string.


Refresh Method (ADO)

Updates the objects in a collection to reflect objects available from and specific to the provider.

Syntax

collection.Refresh

Remarks

The Refresh method accomplishes different tasks depending on the collection from which you call it.

Parameters

Using the Refresh method on a Command object's Parameters collection retrieves provider-side parameter information for the stored procedure or parameterized query specified in the Command object. The collection will be empty for providers that do not support stored procedure calls or parameterized queries.

You should set the ActiveConnection property of the Command object to a valid Connection object, the CommandText property to a valid command, and the CommandType property to adCmdStoredProc before calling the Refresh method.

If you access the Parameters collection before calling the Refresh method, ADO will automatically call the method and populate the collection for you.

Note If you use the Refresh method to obtain parameter information from the provider and it returns one or more variable-length data type Parameter objects, ADO may allocate memory for the parameters based on their maximum potential size, which will cause an error during execution. You should explicitly set the Size property for these parameters before calling the Execute method to prevent errors.

Fields

Using the Refresh method on the Fields collection has no visible effect. To retrieve changes from the underlying database structure, you must use either the Requery method or, if the Recordset object does not support bookmarks, the MoveFirst method.

Properties

Using the Refresh method on a Properties collection of some objects populates the collection with the dynamic properties the provider exposes. These properties provide information about functionality specific to the provider beyond the built-in properties ADO supports.


Refresh Method (RDS)

Requeries the ODBC data source specified in the Connect property and updates the query results.

Syntax

DataControl.Refresh

Parameters

DataControl An object variable that represents an RDS.DataControl object.

Remarks

You must set the Connect, Server, and SQL properties before you use the Refresh method. All data-bound controls on the form associated with an RDS.DataControl object will reflect the new set of records. Any pre-existing Recordset object is released, and any unsaved changes are discarded. The Refresh method automatically makes the first record the current record.

It's a good idea to call the Refresh method periodically when you work with data. If you retrieve data, and then leave it on your client machine for a while, it is likely to become out of date. It's possible that any changes you make will fail, because someone else might have changed the record and submitted changes before you.


Requery Method (ADO)

Updates the data in a Recordset object by re-executing the query on which the object is based.

Syntax

recordset.Requery Options

Parameter

Options Optional. A bitmask indicating options affecting this operation. If this parameter is set to adExecuteAsync, this operation will execute asynchronously and a RecordsetChangeComplete event will be issued when it concludes.

Remarks

Use the Requery method to refresh the entire contents of a Recordset object from the data source by reissuing the original command and retrieving the data a second time. Calling this method is equivalent to calling the Close and Open methods in succession. If you are editing the current record or adding a new record, an error occurs.

While the Recordset object is open, the properties that define the nature of the cursor (CursorType, LockType, MaxRecords, and so forth) are read-only. Thus, the Requery method can only refresh the current cursor. To change any of the cursor properties and view the results, you must use the Close method so that the properties become read/write again. You can then change the property settings and call the Open method to reopen the cursor.


Reset Method (RDS)

Executes the sort or filter on a client-side Recordset based on the specified sort and filter properties.

Syntax

DataControl.Reset(value)

Parameters

DataControl An object variable that represents an RDS.DataControl object.

value Optional. A Boolean value that is True (default) if you want to filter on the current "filtered" rowset. False indicates that you filter on the original rowset, removing any previous filter options.

Remarks

The SortColumn, SortDirection, FilterValue, FilterCriterion, and FilterColumn properties provide sorting and filtering functionality on the client-side cache. The sorting functionality orders records by values from one column. The filtering functionality displays a subset of records based on a find criteria, while the full Recordset is maintained in the cache. The Reset method will execute the criteria and replace the current Recordset with a read-only Recordset.

If there are changes to the original data that haven't yet been submitted, the Reset method will fail. First, use the SubmitChanges method to save any changes in a read/write Recordset, and then use the Reset method to sort or filter the records.

If you want to perform more than one filter on your rowset, you can use the optional Boolean argument with the Reset method. The following example shows how to do this:

ADC.SQL = "Select au_lname from authors"
ADC.Refresh      ' Get the new rowset.

ADC.FilterColumn = "au_lname"
ADC.FilterCriterion = "<"
ADC.FilterValue = "'M'"
ADC.Reset         ' Rowset now has all Last Names < "M".

ADC.FilterCriterion = ">"
ADC.FilterValue = "'F'"
' Passing True is not necessary, because it is the
' default filter on the current "filtered" rowset.
ADC.Reset(TRUE)      ' Rowset now has all Last
                  ' Names < "M" and > "F".

ADC.FilterCriterion = ">"
ADC.FilterValue = "'T'"
' Filter on the original rowset, throwing out the
' previous filter options.
ADC.Reset(FALSE)   ' Rowset now has all Last Names
                  ' > "T".


Resync Method (ADO)

Refreshes the data in the current Recordset object from the underlying database.

Syntax

recordset.Resync AffectRecords, ResyncValues

Parameters

AffectRecords Optional. An AffectEnum value that determines how many records the Resync method will affect. Can be one of the following constants.

Constant | Description
adAffectCurrent | Refresh only the current record.
adAffectGroup | Refresh the records that satisfy the current Filter property setting. You must set the Filter property to one of the valid predefined constants in order to use this option.
adAffectAll | Default. Refresh all the records in the Recordset object, including any hidden by the current Filter property setting.

ResyncValues Optional. A ResyncEnum value that specifies whether underlying values are overwritten. Can be one of the following constants.

Constant | Description
adResyncAllValues | Default. Data is overwritten, and pending updates are canceled.
adResyncUnderlyingValues | Data is not overwritten, and pending updates are not canceled.

Remarks

Use the Resync method to resynchronize records in the current Recordset with the underlying database. This is useful if you are using either a static or forward-only cursor but you want to see any changes in the underlying database.

Unlike the Requery method, the Resync method does not re-execute the Recordset object's underlying command; new records in the underlying database will not be visible.

If the attempt to resynchronize fails because of a conflict with the underlying data (for example, a record has been deleted by another user), the provider returns warnings to the Errors collection and a run-time error occurs. Use the Filter property (adFilterConflictingRecords) and the Status property to locate records with conflicts.

Remote Data Service Usage The Resync method is not available on a client-side Recordset.


Save Method (ADO Recordset)

Saves (persists) the Recordset in a file.

Syntax

recordset.Save FileName, PersistFormat

Parameters

FileName Optional. Complete path name of the file where the Recordset is to be saved.

PersistFormat Optional. The format in which the Recordset is to be saved. Currently the default, and only, valid value is adPersistADTG.

Remarks

The Save method can only be invoked on an open Recordset. Use the Open method to later restore the Recordset from FileName.

If the Filter property is in effect for the Recordset, then only the rows accessible under the filter are saved. If the Recordset is hierarchical, then the current child recordset and its children are saved, but not the parent recordset.

The first time you save the Recordset, specify FileName. If you subsequently invoke Save, omit FileName or else a run-time error will occur. If you subsequently invoke Save with a new FileName, the Recordset is saved to the new file. However, the new file and the original file will both be open.

Save does not close Recordset or FileName, so you can continue to work with the Recordset and save your most recent changes. FileName remains open until the Recordset is closed, during which time other applications can read but not write to FileName.

For reasons of security, the Save method cannot be used from a script executed by Microsoft Internet Explorer.

If the Save method is called while an asynchronous Recordset fetch, execute, or update operation is in progress, then Save waits until the asynchronous operation is complete.

When the Save method is done, the current row position will be the first row of the Recordset.


SubmitChanges Method (RDS)

Submits pending changes of the locally cached updatable Recordset to the ODBC data source specified in the Connect property.

Syntax

DataControl.SubmitChanges

DataFactory.SubmitChanges Connection, Recordset

Parameters

DataControl An object variable that represents an RDS.DataControl object.

DataFactory An object variable that represents an RDSServer.DataFactory object.

Connection A String value that represents the connection created with the RDS.DataControl object's Connect property.

Recordset An object variable that represents a Recordset object.

Remarks

The Connect, Server, and SQL properties must be set before you can use the SubmitChanges method with the RDS.DataControl object.

If you call the CancelUpdate method after you have called SubmitChanges for the same Recordset object, the CancelUpdate call fails because the changes have already been committed.

Only the changed records are sent for modification, and either all of the changes succeed or all of them fail together.

You can use SubmitChanges only with the default RDSServer.DataFactory object. Custom business objects can't use this method.


Supports Method (ADO)

Determines whether a specified Recordset object supports a particular type of functionality.

Syntax

boolean = recordset.Supports( CursorOptions )

Return Value

Returns a Boolean value that indicates whether all of the features identified by the CursorOptions argument are supported by the provider.

Parameters

CursorOptions A Long expression that consists of one or more of the following CursorOptionEnum values.

Constant | Description
adAddNew | You can use the AddNew method to add new records.
adApproxPosition | You can read and set the AbsolutePosition and AbsolutePage properties.
adBookmark | You can use the Bookmark property to gain access to specific records.
adDelete | You can use the Delete method to delete records.
adHoldRecords | You can retrieve more records or change the next retrieve position without committing all pending changes.
adMovePrevious | You can use the MoveFirst and MovePrevious methods, and Move or GetRows methods to move the current record position backward without requiring bookmarks.
adResync | You can update the cursor with the data visible in the underlying database, using the Resync method.
adUpdate | You can use the Update method to modify existing data.
adUpdateBatch | You can use batch updating (UpdateBatch and CancelBatch methods) to transmit changes to the provider in groups.

Remarks

Use the Supports method to determine what types of functionality a Recordset object supports. If the Recordset object supports the features whose corresponding constants are in CursorOptions, the Supports method returns True. Otherwise, it returns False.

Note Although the Supports method may return True for a given functionality, it does not guarantee that the provider can make the feature available under all circumstances. The Supports method simply returns whether or not the provider can support the specified functionality, assuming certain conditions are met. For example, the Supports method may indicate that a Recordset object supports updates even though the cursor is based on a multitable join, some columns of which are not updatable.


Update Method (ADO)

Saves any changes you make to the current record of a Recordset object.

Syntax

recordset.Update Fields, Values

Parameters

Fields Optional. A Variant representing a single name or a Variant array representing names or ordinal positions of the field or fields you wish to modify.

Values Optional. A Variant representing a single value or a Variant array representing values for the field or fields in the new record.

Remarks

Use the Update method to save any changes you make to the current record of a Recordset object since calling the AddNew method or since changing any field values in an existing record. The Recordset object must support updates.

To set field values, do one of the following:

  • Assign values to a Field object's Value property and call the Update method.

  • Pass a field name and a value as arguments with the Update call.

  • Pass an array of field names and an array of values with the Update call.

When you use arrays of fields and values, there must be an equal number of elements in both arrays. Also, the order of field names must match the order of field values. If the number and order of fields and values do not match, an error occurs.

If the Recordset object supports batch updating, then you can cache multiple changes to one or more records locally until you call the UpdateBatch method. If you are editing the current record or adding a new record when you call the UpdateBatch method, ADO will automatically call the Update method to save any pending changes to the current record before transmitting the batched changes to the provider.

If you move from the record you are adding or editing before calling the Update method, ADO will automatically call Update to save the changes. You must call the CancelUpdate method if you want to cancel any changes made to the current record or to discard a newly added record.

The current record remains current after you call the Update method.


UpdateBatch Method (ADO)

Writes all pending batch updates to disk.

Syntax

recordset.UpdateBatch AffectRecords

Parameters

AffectRecords Optional. An AffectEnum value that determines how many records the UpdateBatch method will affect. Can be one of the following constants.

Constant | Description
adAffectCurrent | Write pending changes only for the current record.
adAffectGroup | Write pending changes for the records that satisfy the current Filter property setting. You must set the Filter property to one of the valid predefined constants in order to use this option.
adAffectAll | (Default) Write pending changes for all the records in the Recordset object, including any hidden by the current Filter property setting.

Remarks

Use the UpdateBatch method when modifying a Recordset object in batch update mode to transmit all changes made in a Recordset object to the underlying database.

If the Recordset object supports batch updating, then you can cache multiple changes to one or more records locally until you call the UpdateBatch method. If you are editing the current record or adding a new record when you call the UpdateBatch method, ADO will automatically call the Update method to save any pending changes to the current record before transmitting the batched changes to the provider.

Note You should use batch updating only with either a keyset or static cursor.

If the attempt to transmit changes fails because of a conflict with the underlying data (for example, a record has already been deleted by another user), the provider returns warnings to the Errors collection but does not halt program execution. A run-time error occurs only if there are conflicts on all the requested records. Use the Filter property (adFilterAffectedRecords) and the Status property to locate records with conflicts.

To cancel all pending batch updates, use the CancelBatch method.


BeginTransComplete, CommitTransComplete, and RollbackTransComplete Event Methods (ADO)

BeginTransComplete, CommitTransComplete, and RollbackTransComplete (ConnectionEvent) Methods (ADO)

These Event handling methods will be called after the associated operation on the Connection object finishes executing.

  • BeginTransComplete is called after the BeginTrans operation.

  • CommitTransComplete is called after the CommitTrans operation.

  • RollbackTransComplete is called after the RollbackTrans operation.

Syntax

BeginTransComplete TransactionLevel, pError, adStatus, pConnection

CommitTransComplete pError, adStatus, pConnection

RollbackTransComplete pError, adStatus, pConnection

Parameters

TransactionLevel A Long. Contains the new transaction level of the BeginTrans that caused this event.

pError An Error object. It describes the error that occurred if the value of EventStatusEnum is adStatusErrorsOccurred; otherwise it is not set.

adStatus An EventStatusEnum status value. When any of these methods is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

These methods can prevent subsequent notifications by setting this parameter to adStatusUnwantedEvent before the method returns.

pConnection The Connection object for which this event occurred.

Remarks

In Visual C++ multiple Connections can share the same event handling method. The method uses the returned Connection object to determine which object caused the event.

If the Attributes property is set to adXactCommitRetaining or adXactAbortRetaining, a new transaction is started after committing or rolling back a transaction. Use the BeginTransComplete event handler routine to ignore all but the first transaction start event.


ConnectComplete and Disconnect (ConnectionEvent) Methods (ADO)

The ConnectComplete method is called after a connection starts. The Disconnect method is called after a connection ends.

Syntax

ConnectComplete pError, adStatus, pConnection

Disconnect adStatus, pConnection

Parameters

pError An Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

adStatus An EventStatusEnum status value. When either of these methods is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

When ConnectComplete is called, this parameter is set to adStatusCancel if a WillConnect method has requested cancellation of the pending connection.

Before either method returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.

pConnection The Connection object for which this event applies.


EndOfRecordset (ConnectionEvent) Method (ADO)

The EndOfRecordset method is called when there is an attempt to move to a row past the end of the Recordset.

Syntax

EndOfRecordset fMoreData, adStatus, pRecordset

Parameters

fMoreData A VARIANT_BOOL. It is possible to append new records to pRecordset while processing this event. Before EndOfRecordset returns, add your data, then set this parameter to True to indicate that there is a new end to the Recordset.

adStatus An EventStatusEnum status value.

When EndOfRecordset is called, this parameter is set to adStatusOK if the operation that caused the event was successful. It is set to adStatusCantDeny if this method cannot request cancellation of the operation that caused this event.

Before EndOfRecordset returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.

pRecordset A Recordset object. The Recordset for which this event occurred.

Remarks

An EndOfRecordset event may occur if the Recordset.MoveNext operation fails.

This event handler is called when the user attempts to move past the end of pRecordset, perhaps as a result of calling MoveNext. However, while in this method the user could retrieve more records from a database and append them to the end of pRecordset. In that case, the user would set fMoreData to VARIANT_TRUE, and return from EndOfRecordset. Then the user could call MoveNext again to access the newly retrieved records.


ExecuteComplete (ConnectionEvent) Method (ADO)

This method is called after a command has finished executing.

Syntax

ExecuteComplete RecordsAffected, pError, adStatus, pCommand, pRecordset, pConnection

Parameters

RecordsAffected A Long. The number of records affected by the command.

pError An Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

adStatus An EventStatusEnum status value. When this method is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

Before this method returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.

pCommand The Command object, if any, that was executed.

pRecordset A Recordset object. The result of the execution. This recordset may be empty.

pConnection A Connection object. The connection on which the command was executed.

Remarks

An ExecuteComplete event may occur due to Connection.Execute, Command.Execute, Recordset.Open, or Recordset.NextRecordset.


FetchComplete (RecordsetEvent) Method (ADO)

This method is called after all the records in a lengthy asynchronous operation have been retrieved (fetched) into the Recordset.

Syntax

FetchComplete pError, adStatus, pRecordset

Parameters

pError An Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

adStatus An EventStatusEnum status value. When this method is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

Before this method returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.

pRecordset A Recordset object. The object for which the records were retrieved.


FetchProgress (RecordsetEvent) Method (ADO)

This method is called periodically during a lengthy asynchronous operation to report how many rows have currently been retrieved (fetched) into the Recordset.

Syntax

FetchProgress Progress, MaxProgress, pRecordset

Parameters

Progress A Long. The number of records that have currently been retrieved.

MaxProgres A Long. The maximum number of records expected to be retrieved.

pRecordset A Recordset object. The object for which the records are being retrieved.


InfoMessage (ConnectionEvent) Method (ADO)

This method is called whenever a ConnectionEvent operation completes successfully and additional information is returned by a provider.

Syntax

InfoMessage pError, adStatus, pConnection

Parameters

pError An Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set. Multiple warnings can be returned, which can be found by enumerating the Errors collection.

adStatus An EventStatusEnum status value. When this method is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

Before this method returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.

pConnection A Connection object. The connection on which the command was executed.


onError (Event) Method (RDS)

This method is called whenever an error occurs during an operation.

Syntax

onError SCode, Description, Source, CancelDisplay

Parameters

SCode An integer, which contains the status code of the error.

Description A string, which contains a description of the error.

Source A string, which contains the query or command that caused the error.

CancelDisplay A Boolean, which if set to True, prevents the error from being displayed in a dialog box.


onReadyStateChange (Event) Method (RDS)

This method is called whenever the value of the ReadyState property changes.

Syntax

onReadyStateChange

Parameters

None

Remarks

The ReadyState property reflects the progress of an RDS.DataControl object as it asynchronously fetches data into its Recordset object. Use the onReadyStateChange method to monitor changes in the ReadyState property whenever they occur. This is more efficient than periodically checking the property's value.


WillChangeField and FieldChangeComplete (ConnectionEvent) Methods (ADO)

The WillChangeField method is called before a pending operation changes the value of one or more Field objects in the Recordset. The FieldChangeComplete method is called after the value of one or more Field objects has changed.

Syntax

WillChangeField cFields, Fields, adStatus, pRecordset

FieldChangeComplete cFields, Fields, pError, adStatus, pRecordset

Parameters

cFields A Long. The number of Field objects in Fields.

Fields An array of Variants. Contains Field objects with pending changes.

pError An Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

adStatus An EventStatusEnum status value.

When WillChangeField is called, this parameter is set to adStatusOK if the operation that caused the event was successful. It is set to adStatusCantDeny if this method cannot request cancellation of the pending operation.

When FieldChangeComplete is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

Before WillChangeField returns, set this parameter to adStatusCancel to request cancellation of the pending operation.

Before FieldChangeComplete returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.

pRecordset A Recordset object. The Recordset for which this event occurred.

Remarks

A WillChangeField or FieldChangeComplete event may occur due to the following Recordset operations: Value, and Update with field and value array parameters.


WillChangeRecord and RecordChangeComplete (ConnectionEvent) Methods (ADO)

The WillChangeRecord method is called before one or more records (rows) in the Recordset change. The RecordChangeComplete method is called after one or more records change.

Syntax

WillChangeRecord adReason, cRecords, adStatus, pRecordset

RecordChangeComplete adReason, cRecords, pError, adStatus, pRecordset

Parameters

adReason An EventReasonEnum value. Specifies the reason for this event. Its value can be adRsnAddNew, adRsnDelete, adRsnUpdate, adRsnUndoUpdate, adRsnUndoAddNew, adRsnUndoDelete, or adRsnFirstChange.

cRecords A Long. The number of records changing (affected).

pError An Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

adStatus An EventStatusEnum status value.

When WillChangeRecord is called, this parameter is set to adStatusOK if the operation that caused the event was successful. It is set to adStatusCantDeny if this method cannot request cancellation of the pending operation.

When RecordChangeComplete is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

Before WillChangeRecord returns, set this parameter to adStatusCancel to request cancellation of the operation that caused this event.

Before RecordChangeComplete returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.

pRecordset A Recordset object. The Recordset for which this event occurred.

Remarks

A WillChangeRecord or RecordChangeComplete event may occur due to the following Recordset operations: Update, Delete, CancelUpdate, AddNew, UpdateBatch, and CancelBatch.

During the WillChangeRecord event, the Recordset Filter property is set to adFilterAffectedRecords. It is illegal to change this property while processing the event.


WillChangeRecordset and RecordsetChangeComplete (ConnectionEvent) Methods (ADO)

The WillChangeRecordset method is called before a pending operation changes the Recordset. The RecordsetChangeComplete method is called after the Recordset has changed.

Syntax

WillChangeRecordset adReason, adStatus, pRecordset

RecordsetChangeComplete adReason, pError, adStatus, pRecordset

Parameters

adReason An EventReasonEnum value. Specifies the reason for this event. Its value can be adRsnReQuery, adRsnReSynch, adRsnClose, adRsnOpen.

adStatus An EventStatusEnum status value.

When WillChangeRecordset is called, this parameter is set to adStatusOK if the operation that caused the event was successful. It is set to adStatusCantDeny if this method cannot request cancellation of the pending operation.

When RecordsetChangeComplete is called, this parameter is set to adStatusOK if the operation that caused the event was successful, adStatusErrorsOccurred if the operation failed, or adStatusCancel if the operation associated with the previously accepted WillChangeRecordset event has been canceled.

Before WillChangeRecordset returns, set this parameter to adStatusCancel to request cancellation of the pending operation.

Before WillChangeRecordset or RecordsetChangeComplete returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.

pError An Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

pRecordset A Recordset object. The Recordset for which this event occurred.

Remarks

A WillChangeRecordset or RecordsetChangeComplete event may occur due to the following Recordset operations: Requery, Resync, Close, Open, and Filter.


WillConnect (ConnectionEvent) Method (ADO)

This method is called before a connection starts. The parameters to be used in the pending connection are supplied as input parameters and can be changed before the method returns. This method may return a request that the pending connection be canceled.

Syntax

WillConnect ConnectionString, UserID, Password, Options, adStatus, pConnection

Parameters

ConnectionString A String containing connection information for the pending connection.

UserID A String containing a user name for the pending connection.

Password A String containing a password for the pending connection.

Options A Long value that indicates how the provider should evaluate the ConnectionString. See the CommandType property for a list of acceptable values.

adStatus An EventStatusEnum status value.

When this method is called, this parameter is set to adStatusOK if the operation that caused the event was successful. This parameter is set to adStatusCantDeny if this method cannot request cancellation of the pending operation.

Before this method returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications. Set this parameter to adStatusCancel to request the connection operation that caused cancellation of this notification.

pConnection The Connection object for which this event notification applies.

Remarks

When this method is called, the ConnectionString, UserID, Password, and Options parameters are set to the values established by the operation that caused this event.

When this method is canceled, ConnectComplete will be called with its adStatus parameter set to adStatusErrorsOccurred.


WillExecute (ConnectionEvent) Method (ADO)

This method is called just before a pending command executes on this connection and affords the user an opportunity to examine and modify the pending execution parameters. This method may return a request that the pending command be canceled.

Syntax

WillExecute Source, CursorType, LockType, Options, adStatus, pCommand, pRecordset, pConnection

Parameters

Source A String containing an SQL command or a stored procedure name.

CursorType A CursorTypeEnum containing the type of cursor for the recordset that will be opened. This parameter cannot be changed if it is set to adOpenUnspecified when this method is called.

LockType A LockTypeEnum containing the lock type for the recordset that will be opened. This parameter cannot be changed if it is set to adLockUnspecified when this method is called.

Options A Long value of options that can be used to execute the command or open the recordset.

adStatus An EventStatusEnum status value that may be adStatusCantDeny or adStatusOK when this method is called. If it is adStatusCantDeny, this method may not request cancellation of the pending operation.

Before this method returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications, or adStatusCancel to request cancellation of the operation that caused this event.

pCommand The Command object for which this event notification applies.

pRecordset The Recordset object for which this event notification applies.

pConnection The Connection object for which this event notification applies.

Remarks

A WillExecute event may occur due to Connection.Execute, Command.Execute, or Recordset.Open. The corresponding pConnection, pCommand, or pRecordset parameter will be set to the object causing the event and the remaining two will be set to Nothing.


WillMove and MoveComplete (ConnectionEvent) Methods (ADO)

The WillMove method is called before a pending operation changes the current position in the Recordset. The MoveComplete method is called after the current position in the Recordset changes.

Syntax

WillMove adReason, adStatus, pRecordset

MoveComplete adReason, pError, adStatus, pRecordset

Parameters

adReason An EventReasonEnum value. Specifies the reason for this event. Its value can be adRsnMoveFirst, adRsnMoveLast, adRsnMoveNext, adRsnMovePrevious, adRsnMove or adRsnRequery.

pError An Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

adStatus An EventStatusEnum status value.

When WillMove is called, this parameter is set to adStatusOK if the operation that caused the event was successful. It is set to adStatusCantDeny if this method cannot request cancellation of the pending operation.

When MoveComplete is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

Before WillMove returns, set this parameter to adStatusCancel to request cancellation of the pending operation. Before MoveComplete returns, set this parameter to adStatusUnwantedEvent to prevent subsequent notifications.

pRecordset A Recordset object. The Recordset for which this event occurred.

Remarks

A WillMove or MoveComplete event may occur due to the following Recordset operations: Open, Move, MoveFirst, MoveLast, MoveNext, MovePrevious, Bookmark, AddNew, Delete, Requery, and Resync.


AbsolutePage Property (ADO)

Specifies in which page the current record resides.

Settings and Return Values

Sets or returns a Long value from 1 to the number of pages in the Recordset object (PageCount), or returns one of the following constants.

Constant | Description
adPosUnknown | The Recordset is empty, the current position is unknown, or the provider does not support the AbsolutePage property.
adPosBOF | The current record pointer is at BOF (that is, the BOF property is True).
adPosEOF | The current record pointer is at EOF (that is, the EOF property is True).

Remarks

Use the AbsolutePage property to identify the page number on which the current record is located. Use the PageSize property to logically divide the Recordset object into a series of pages, each of which has the number of records equal to PageSize (except for the last page, which may have fewer records). The provider must support the appropriate functionality for this property to be available.

Like the AbsolutePosition property, AbsolutePage is 1-based and equals 1 when the current record is the first record in the Recordset. Set this property to move to the first record of a particular page. Obtain the total number of pages from the PageCount property.


AbsolutePosition Property (ADO)

Specifies the ordinal position of a Recordset object's current record.

Settings and Return Values

Sets or returns a Long value from 1 to the number of records in the Recordset object (RecordCount), or returns one of the following constants.

Constant | Description
adPosUnknown | The Recordset is empty, the current position is unknown, or the provider does not support the AbsolutePosition property.
adPosBOF | The current record pointer is at BOF (that is, the BOF property is True).
adPosEOF | The current record pointer is at EOF (that is, the EOF property is True).

Remarks

Use the AbsolutePosition property to move to a record based on its ordinal position in the Recordset object, or to determine the ordinal position of the current record. The provider must support the appropriate functionality for this property to be available.

Like the AbsolutePage property, AbsolutePosition is 1-based and equals 1 when the current record is the first record in the Recordset. You can obtain the total number of records in the Recordset object from the RecordCount property.

When you set the AbsolutePosition property, even if it is to a record in the current cache, ADO reloads the cache with a new group of records starting with the record you specified. The CacheSize property determines the size of this group.

Note You should not use the AbsolutePosition property as a surrogate record number. The position of a given record changes when you delete a preceding record. There is also no assurance that a given record will have the same AbsolutePosition if the Recordset object is requeried or reopened. Bookmarks are still the recommended way of retaining and returning to a given position and are the only way of positioning across all types of Recordset objects.


ActiveCommand Property (ADO)

Indicates the Command object that created the associated Recordset object.

Return Value

Returns a Variant containing a Command object. Default is a Null object reference.

Remarks

The ActiveCommand property is read-only.

If a Command object was not used to create the current Recordset, then a Null object reference is returned.

Use this property to find the associated Command object when you are given only the resulting Recordset object.


ActiveConnection Property (ADO)

Indicates to which Connection object the specified Command or Recordset object currently belongs.

Settings and Return Values

Sets or returns a String containing the definition for a connection or a Connection object. Default is a Null object reference.

Remarks

Use the ActiveConnection property to determine the Connection object over which the specified Command object will execute or the specified Recordset will be opened.

Command

For Command objects, the ActiveConnection property is read/write.

If you attempt to call the Execute method on a Command object before setting this property to an open Connection object or valid connection string, an error occurs.

Microsoft Visual Basic Setting the ActiveConnection property to Nothing disassociates the Command object from the current Connection and causes the provider to release any associated resources on the data source. You can then associate the Command object with the same or another Connection object. Some providers allow you to change the property setting from one Connection to another, without having to first set the property to Nothing.

If the Parameters collection of the Command object contains parameters supplied by the provider, the collection is cleared if you set the ActiveConnection property to Nothing or to another Connection object. If you manually create Parameter objects and use them to fill the Parameters collection of the Command object, setting the ActiveConnection property to Nothing or to another Connection object leaves the Parameters collection intact.

Closing the Connection object with which a Command object is associated sets the ActiveConnection property to Nothing. Setting this property to a closed Connection object generates an error.

Recordset

For open Recordset objects or for Recordset objects whose Source property is set to a valid Command object, the ActiveConnection property is read-only. Otherwise, it is read/write.

You can set this property to a valid Connection object or to a valid connection string. In this case, the provider creates a new Connection object using this definition and opens the connection. Additionally, the provider may set this property to the new Connection object to give you a way to access the Connection object for extended error information or to execute other commands.

If you use the ActiveConnection argument of the Open method to open a Recordset object, the ActiveConnection property will inherit the value of the argument.

If you set the Source property of the Recordset object to a valid Command object variable, the ActiveConnection property of the Recordset inherits the setting of the Command object's ActiveConnection property.

Remote Data Service Usage When used on a client-side (ADOR) Recordset object, this property can be set only to a connection string or (in Microsoft Visual Basic or VBScript) to Nothing.


ActualSize Property (ADO)

Indicates the actual length of a field's value.

Settings and Return Values

Returns a Long value. Some providers may allow this property to be set to reserve space for BLOB data, in which case the default value is 0.

Remarks

Use the ActualSize property to return the actual length of a Field object's value. For all fields, the ActualSize property is read-only. If ADO cannot determine the length of the Field object's value, the ActualSize property returns adUnknown.

The ActualSize and DefinedSize properties are different as shown in the following example: a Field object with a declared type of adVarChar and a maximum length of 50 characters returns a DefinedSize property value of 50, but the ActualSize property value it returns is the length of the data stored in the field for the current record.


Attributes Property (ADO)

Indicates one or more characteristics of an object.

Settings and Return Values

Sets or returns a Long value.

For a Connection object, the Attributes property is read/write, and its value can be the sum of any one or more of these XactAttributeEnum values (default is zero).

Constant | Description
adXactCommitRetaining | Performs retaining commits—that is, calling CommitTrans automatically starts a new transaction. Not all providers support this.
adXactAbortRetaining | Performs retaining aborts—that is, calling RollbackTrans automatically starts a new transaction. Not all providers support this.

For a Parameter object, the Attributes property is read/write, and its value can be the sum of any one or more of these ParameterAttributesEnum values.

Constant | Description
adParamSigned | Default. Indicates that the parameter accepts signed values.
adParamNullable | Indicates that the parameter accepts Null values.
adParamLong | Indicates that the parameter accepts long binary data.

For a Field object, the Attributes property is read-only, and its value can be the sum of any one or more of these FieldAttributeEnum values.

Constant | Description
adFldMayDefer | Indicates that the field is deferred—that is, the field values are not retrieved from the data source with the whole record, but only when you explicitly access them.
adFldUpdatable | Indicates that you can write to the field.
adFldUnknownUpdatable | Indicates that the provider cannot determine if you can write to the field.
adFldFixed | Indicates that the field contains fixed-length data.
adFldIsNullable | Indicates that the field accepts Null values.
adFldMayBeNull | Indicates that you can read Null values from the field.
adFldLong | Indicates that the field is a long binary field. Also indicates that you can use the AppendChunk and GetChunk methods.
adFldRowID | Indicates that the field contains a persistent row identifier that cannot be written to and has no meaningful value except to identify the row (such as a record number, unique identifier, and so forth).
adFldRowVersion | Indicates that the field contains some kind of time or date stamp used to track updates.
adFldCacheDeferred | Indicates that the provider caches field values and that subsequent reads are done from the cache.

For a Property object, the Attributes property is read-only, and its value can be the sum of any one or more of these PropertyAttributesEnum values:

Constant | Description
adPropNotSupported | Indicates that the property is not supported by the provider.
adPropRequired | Indicates that the user must specify a value for this property before the data source is initialized.
adPropOptional | Indicates that the user does not need to specify a value for this property before the data source is initialized.
adPropRead | Indicates that the user can read the property.
adPropWrite | Indicates that the user can set the property.

Remarks

Use the Attributes property to set or return characteristics of Connection objects, Parameter objects, Field objects, or Property objects.

When you set multiple attributes, you can sum the appropriate constants. If you set the property value to a sum including incompatible constants, an error occurs.

Remote Data Service Usage This property is not available on a client-side Connection object.


BOF, EOF Properties (ADO)

  • BOF indicates that the current record position is before the first record in a Recordset object.

  • EOF indicates that the current record position is after the last record in a Recordset object.

Return Value

The BOF and EOF properties return Boolean values.

Remarks

Use the BOF and EOF properties to determine whether a Recordset object contains records or whether you've gone beyond the limits of a Recordset object when you move from record to record.

The BOF property returns True (-1) if the current record position is before the first record and False (0) if the current record position is on or after the first record.

The EOF property returns True if the current record position is after the last record and False if the current record position is on or before the last record.

If either the BOF or EOF property is True, there is no current record.

If you open a Recordset object containing no records, the BOF and EOF properties are set to True, and the Recordset object's RecordCount property setting is zero. When you open a Recordset object that contains at least one record, the first record is the current record and the BOF and EOF properties are False.

If you delete the last remaining record in the Recordset object, the BOF and EOF properties may remain False until you attempt to reposition the current record.

This table shows which Move methods are allowed with different combinations of the BOF and EOF properties.

 | MoveFirst, MoveLast | MovePrevious, Move < 0 | Move 0 | MoveNext, Move > 0
BOF=True, EOF=False | Allowed | Error | Error | Allowed
BOF=False, EOF=True | Allowed | Allowed | Error | Error
Both True | Error | Error | Error | Error
Both False | Allowed | Allowed | Allowed | Allowed

Allowing a Move method doesn't guarantee that the method will successfully locate a record; it only means that calling the specified Move method won't generate an error.

The following table shows what happens to the BOF and EOF property settings when you call various Move methods but are unable to successfully locate a record.

 | BOF | EOF
MoveFirst, MoveLast | Set to True | Set to True
Move 0 | No change | No change
MovePrevious, Move < 0 | Set to True | No change
MoveNext, Move > 0 | No change | Set to True


Bookmark Property (ADO)

Returns a bookmark that uniquely identifies the current record in a Recordset object or sets the current record in a Recordset object to the record identified by a valid bookmark.

Settings and Return Values

Sets or returns a Variant expression that evaluates to a valid bookmark.

Remarks

Use the Bookmark property to save the position of the current record and return to that record at any time. Bookmarks are available only in Recordset objects that support bookmark functionality.

When you open a Recordset object, each of its records has a unique bookmark. To save the bookmark for the current record, assign the value of the Bookmark property to a variable. To quickly return to that record at any time after moving to a different record, set the Recordset object's Bookmark property to the value of that variable.

The user may not be able to view the value of the bookmark. Also, users should not expect bookmarks to be directly comparable—two bookmarks that refer to the same record may have different values.

If you use the Clone method to create a copy of a Recordset object, the Bookmark property settings for the original and the duplicate Recordset objects are identical and you can use them interchangeably. However, you cannot use bookmarks from different Recordset objects interchangeably, even if they were created from the same source or command.

Remote Data Service Usage When used on a client-side (ADOR) Recordset object, the Bookmark property is always available.


CacheSize Property (ADO)

Indicates the number of records from a Recordset object that are cached locally in memory.

Settings and Return Values

Sets or returns a Long value that must be greater than 0. Default is 1.

Remarks

Use the CacheSize property to control how many records the provider keeps in its buffer and how many to retrieve at one time into local memory. For example, if the CacheSize is 10, after first opening the Recordset object, the provider retrieves the first 10 records into local memory. As you move through the Recordset object, the provider returns the data from the local memory buffer. As soon as you move past the last record in the cache, the provider retrieves the next 10 records from the data source into the cache.

The value of this property can be adjusted during the life of the Recordset object, but changing this value only affects the number of records in the cache after subsequent retrievals from the data source. Changing the property value alone will not change the current contents of the cache.

If there are fewer records to retrieve than CacheSize specifies, the provider returns the remaining records; no error occurs.

A CacheSize setting of zero is not allowed and returns an error.

Records retrieved from the cache don't reflect concurrent changes that other users made to the source data. To force an update of all the cached data, use the Resync method.


CommandText Property (ADO)

Contains the text of a command that you want to issue against a provider.

Settings and Return Values

Sets or returns a String value containing a provider command, such as an SQL statement, a table name, or a stored procedure call. Default is "" (zero-length string).

Remarks

Use the CommandText property to set or return the text of a Command object. Usually, this will be an SQL statement, but can also be any other type of command statement recognized by the provider, such as a stored procedure call. An SQL statement must be of the particular dialect or version supported by the provider’s query processor.

If the Prepared property of the Command object is set to True and the Command object is bound to an open connection when you set the CommandText property, ADO prepares the query (that is, a compiled form of the query is stored by the provider) when you call the Execute or Open methods.

Depending on the CommandType property setting, ADO may alter the CommandText property. You can read the CommandText property at any time to see the actual command text that ADO will use during execution.


CommandTimeout Property (ADO)

Indicates how long to wait while executing a command before terminating the attempt and generating an error.

Settings and Return Values

Sets or returns a Long value that indicates, in seconds, how long to wait for a command to execute. Default is 30.

Remarks

Use the CommandTimeout property on a Connection object or Command object to allow the cancellation of an Execute method call, due to delays from network traffic or heavy server use. If the interval set in the CommandTimeout property elapses before the command completes execution, an error occurs and ADO cancels the command. If you set the property to zero, ADO will wait indefinitely until the execution is complete. Make sure the provider and data source to which you are writing code supports the CommandTimeout functionality.

The CommandTimeout setting on a Connection object has no effect on the CommandTimeout setting on a Command object on the same Connection; that is, the Command object’s CommandTimeout property does not inherit the value of the Connection object’s CommandTimeout value.

On a Connection object, the CommandTimeout property remains read/write after the Connection is opened.


CommandType Property (ADO)

Indicates the type of a Command object.

Settings and Return Values

Sets or returns one of the following CommandTypeEnum values.

Constant | Description
adCmdText | Evaluates CommandText as a textual definition of a command or stored procedure call.
adCmdTable | Evaluates CommandText as a table name whose columns are all returned by an internally generated SQL query.
adCmdTableDirect | Evaluates CommandText as a table name whose columns are all returned.
adCmdStoredProc | Evaluates CommandText as a stored procedure name.
adCmdUnknown | Default. The type of command in the CommandText property is not known.
adCommandFile | Evaluates CommandText as the file name of a persisted Recordset.
adExecuteNoRecords | Indicates CommandText is a command or stored procedure that does not return rows (for example, a command that only inserts data). If any rows are retrieved, they are discarded and not returned. Always combined with adCmdText or adCmdStoredProc.

Remarks

Use the CommandType property to optimize evaluation of the CommandText property.

If the CommandType property value equals adCmdUnknown (the default value), you may experience diminished performance because ADO must make calls to the provider to determine if the CommandText property is an SQL statement, a stored procedure, or a table name. If you know what type of command you're using, setting the CommandType property instructs ADO to go directly to the relevant code. If the CommandType property does not match the type of command in the CommandText property, an error occurs when you call the Execute method.

The adExecuteNoRecords constant improves performance by minimizing internal processing. This constant never stands alone; it is always combined with adCmdText or adCmdStoredProc (for example, adCmdText+adExecuteNoRecords). An error results if adExecuteNoRecords is used with the Recordset.Open method, or a Command object used by that method.


Connect Property (RDS)

Sets or returns the database name from which the query and update operations are run.

You can set the Connect property at design time in the RDS.DataControl object's OBJECT tags, or at run time in scripting code (for instance, VBScript).

Syntax

Design time: <PARAM NAME="Connect" VALUE="DSN=DSNName;UID=usr;PWD=pw;">

Run time: DataControl.Connect = "DSN=DSNName;UID=usr;PWD=pw;"

Parameters

DSNName A String that specifies the system data source name that identifies a specific database.

usr A String that represents a valid user account on the server.

pw A String that represents a valid password for the user account.

DataControl An object variable that represents an RDS.DataControl object.


ConnectionString Property (ADO)

Contains the information used to establish a connection to a data source.

Settings and Return Values

Sets or returns a String value.

Remarks

Use the ConnectionString property to specify a data source by passing a detailed connection string containing a series of argument = value statements separated by semicolons.

ADO supports four arguments for the ConnectionString property; any other arguments pass directly to the provider without any processing by ADO. The arguments ADO supports are as follows:

Argument | Description
Provider= | Specifies the name of a provider to use for the connection.
File Name= | Specifies the name of a provider-specific file (for example, a persisted data source object) containing preset connection information.
Remote Provider= | Specifies the name of a provider to use when opening a client-side connection. (Remote Data Service only.)
Remote Server= | Specifies the path name of the sever to use when opening a client-side connection. (Remote Data Service only.)

After you set the ConnectionString property and open the Connection object, the provider may alter the contents of the property, for example, by mapping the ADO-defined argument names to their provider equivalents.

The ConnectionString property automatically inherits the value used for the ConnectionString argument of the Open method, so you can override the current ConnectionString property during the Open method call.

Because the File Name argument causes ADO to load the associated provider, you cannot pass both the Provider and File Name arguments.

The ConnectionString property is read/write when the connection is closed and read-only when it is open.

Remote Data Service Usage When used on a client-side Connection object, the ConnectionString property can include only the Remote Provider and Remote Server parameters.


ConnectionTimeout Property (ADO)

Indicates how long to wait while establishing a connection before terminating the attempt and generating an error.

Settings and Return Values

Sets or returns a Long value that indicates, in seconds, how long to wait for the connection to open. Default is 15.

Remarks

Use the ConnectionTimeout property on a Connection object if delays from network traffic or heavy server use make it necessary to abandon a connection attempt. If the time from the ConnectionTimeout property setting elapses prior to the opening of the connection, an error occurs and ADO cancels the attempt. If you set the property to zero, ADO will wait indefinitely until the connection is opened. Make sure the provider to which you are writing code supports the ConnectionTimeout functionality.

The ConnectionTimeout property is read/write when the connection is closed and read-only when it is open.


Count Property (ADO)

Indicates the number of objects in a collection.

Return Value

Returns a Long value.

Remarks

Use the Count property to determine how many objects are in a given collection.

Because numbering for members of a collection begins with zero, you should always code loops starting with the zero member and ending with the value of the Count property minus 1. If you are using Microsoft® Visual Basic® and want to loop through the members of a collection without checking the Count property, use the For Each...Next command.

If the Count property is zero, there are no objects in the collection.


CursorLocation Property (ADO)

Sets or returns the location of the cursor engine.

Settings And Return Values

Sets or returns a Long value that can be set to one of the following constants.

Constant | Description
adUseNone | No cursor services are used. (This constant is obsolete and appears solely for the sake of backward compatibility.)
adUseClient | Uses client-side cursors supplied by a local cursor library. Local cursor engines often will allow many features that driver-supplied cursors may not, so using this setting may provide an advantage with respect to features that will be enabled. For backward compatibility, the synonym adUseClientBatch is also supported.
adUseServer | Default. Uses data-provider– or driver-supplied cursors. These cursors are sometimes very flexible and allow for additional sensitivity to changes others make to the data source. However, some features of the Microsoft Client Cursor Provider (such as disassociated recordsets) cannot be simulated with server-side cursors and these features will be unavailable with this setting.

Remarks

This property allows you to choose between various cursor libraries accessible to the provider. Usually, you can choose between using a client-side cursor library or one that is located on the server.

This property setting affects connections established only after the property has been set. Changing the CursorLocation property has no effect on existing connections.

This property is read/write on a Connection or a closed Recordset, and read-only on an open Recordset.

Connection.Execute cursors will inherit this setting. Recordsets will automatically inherit this setting from their associated connections.

Remote Data Service Usage When used on a client-side (ADOR) Recordset or Connection object, the CursorLocation property can only be set to adUseClient.


CursorType Property (ADO)

Indicates the type of cursor used in a Recordset object.

Settings and Return Values

Sets or returns one of the following CursorTypeEnum values.

Constant | Description
adOpenForwardOnly | Forward-only cursor. Default. Identical to a static cursor except that you can only scroll forward through records. This improves performance in situations when you need to make only a single pass through a recordset.
adOpenKeyset | Keyset cursor. Like a dynamic cursor, except that you can't see records that other users add, although records that other users delete are inaccessible from your recordset. Data changes by other users are still visible.
adOpenDynamic | Dynamic cursor. Additions, changes, and deletions by other users are visible, and all types of movement through the recordset are allowed, except for bookmarks if the provider doesn't support them.
adOpenStatic | Static cursor. A static copy of a set of records that you can use to find data or generate reports. Additions, changes, or deletions by other users are not visible.

Remarks

Use the CursorType property to specify the type of cursor that should be used when opening the Recordset object. The CursorType property is read/write when the Recordset is closed and read-only when it is open.

Only a setting of adUseStatic is supported if the CursorLocation property is set to adUseClient. If an unsupported value is set, then no error will result; the closest supported CursorType will be used instead.

If a provider does not support the requested cursor type, the provider may return another cursor type. The CursorType property will change to match the actual cursor type in use when the Recordset object is open. To verify specific functionality of the returned cursor, use the Supports method. After you close the Recordset, the CursorType property reverts to its original setting.

The following chart shows the provider functionality (identified by Supports method constants) required for each cursor type.

For a Recordset of this CursorType | The Supports method must return True for all of these constants
adOpenForwardOnly | none
adOpenKeyset | adBookmark, adHoldRecords, adMovePrevious, adResync
adOpenDynamic | adMovePrevious
adOpenStatic | adBookmark, adHoldRecords, adMovePrevious, adResync

Note Although Supports(adUpdateBatch) may be true for dynamic and forward-only cursors, for batch updates you should use either a keyset or static cursor. Set the LockType property to adLockBatchOptimistic, and the CursorLocation property to adUseClient to enable the Microsoft Client Cursor Engine, which is required for batch updates.

Remote Data Service Usage When used on a client-side (ADOR) Recordset object, the CursorType property can be set only to adOpenStatic.


DataMember Property (ADO)

The name of the data member to retrieve from the object referenced by the DataSource property.

Settings and Return Values

Sets or returns a String value. The name is not case sensitive.

Remarks

This property is used to create data-bound controls with the Data Environment. The Data Environment maintains collections of data (data sources) containing named objects (data members) that will be represented as a Recordset object.

The DataMember and DataSource properties must be used in conjunction.

The DataMember property determines which object specified by the DataSource property will be represented as a Recordset object. The Recordset object must be closed before this property is set. An error is generated if the DataMember property isn't set before the DataSource property, or if the DataMember name isn't recognized by the object specified in the DataSource property.

See the Control Writer section of the Data Access SDK for more information.

Usage

Dim rs as New ADODB.Recordset
rs.DataMember = "Command"      'Name of the rowset to bind to
Set rs.DataSource = myDE      'Name of the object containing an IRowset


DataSource Property (ADO)

Specifies an object containing data to be represented as a Recordset object.

Remarks

This property is used to create data-bound controls with the Data Environment. The Data Environment maintains collections of data (data sources) containing named objects (data members) that will be represented as a Recordset object.

The DataMember and DataSource properties must be used in conjunction.

The object referenced must implement the IDataSource interface and must contain an IRowset interface.

See the Control Writer section of the Data Access SDK for more information.

Usage

Dim rs as New ADODB.Recordset
rs.DataMember = "Command"      'Name of the rowset to bind to
Set rs.DataSource = myDE      'Name of the object containing an IRowset


DefaultDatabase Property (ADO)

Indicates the default database for a Connection object.

Settings and Return Values

Sets or returns a String that evaluates to the name of a database available from the provider.

Remarks

Use the DefaultDatabase property to set or return the name of the default database on a specific Connection object.

If there is a default database, SQL strings may use an unqualified syntax to access objects in that database. To access objects in a database other than the one specified in the DefaultDatabase property, you must qualify object names with the desired database name. Upon connection, the provider will write default database information to the DefaultDatabase property. Some providers allow only one database per connection, in which case you cannot change the DefaultDatabase property.

Some data sources and providers may not support this feature, and may return an error or an empty string.

Remote Data Service Usage This property is not available on a client-side Connection object.


DefinedSize Property (ADO)

Indicates the defined size of a Field object.

Return Value

Returns a Long value that reflects the defined size of a field as a number of bytes.

Remarks

Use the DefinedSize property to determine the data capacity of a Field object.

The DefinedSize and ActualSize properties are different. For example, consider a Field object with a declared type of adVarChar and a DefinedSize property value of 50, containing a single character. The ActualSize property value it returns is the length in bytes of the single character.


Description Property (ADO)

A descriptive string associated with an Error object.

Return Value

Returns a String value.

Remarks

Use the Description property to obtain a short description of the error. Display this property to alert the user to an error that you cannot or do not want to handle. The string will come from either ADO or a provider.

Providers are responsible for passing specific error text to ADO. ADO adds an Error object to the Errors collection for each provider error or warning it receives. Enumerate the Errors collection to trace the errors that the provider passes.


Direction Property (ADO)

Indicates whether the Parameter represents an input parameter, an output parameter, or both, or if the parameter is the return value from a stored procedure.

Settings and Return Values

Sets or returns one of the following ParameterDirectionEnum values.

Constant | Description
adParamUnknown | Indicates parameter direction is unknown.
adParamInput | Default. Indicates an input parameter.
adParamOutput | Indicates an output parameter.
adParamInputOutput | Indicates both an input and output parameter.
adParamReturnValue | Indicates a return value.

Remarks

Use the Direction property to specify how a parameter is passed to or from a procedure. The Direction property is read/write; this allows you to work with providers that don't return this information or to set this information when you don't want ADO to make an extra call to the provider to retrieve parameter information.

Not all providers can determine the direction of parameters in their stored procedures. In these cases, you must set the Direction property before you execute the query.


EditMode Property (ADO)

Indicates the editing status of the current record.

Return Value

Returns one of the following EditModeEnum values.

Constant | Description
adEditNone | Indicates that no editing operation is in progress.
adEditInProgress | Indicates that data in the current record has been modified but not yet saved.
adEditAdd | Indicates that the AddNew method has been invoked, and the current record in the copy buffer is a new record that hasn't been saved in the database.
adEditDelete | Indicates that the current record has been deleted.

Remarks

ADO maintains an editing buffer associated with the current record. This property indicates whether changes have been made to this buffer, or whether a new record has been created. Use the EditMode property to determine the editing status of the current record. You can test for pending changes if an editing process has been interrupted and determine whether you need to use the Update or CancelUpdate method.

See the AddNew method for a more detailed description of the EditMode property under different editing conditions.


ExecuteOptions Property (RDS)

Indicates whether or not asynchronous execution is enabled.

Settings

The ExecuteOptions property can be either of the following values.

Constant | Description
adcExecSync | Executes the next refresh of the Recordset synchronously.
adcExecAsync | Default. Executes the next refresh of the Recordset asynchronously.

Note Each client-side executable file that uses these constants must provide declarations for them. You can cut and paste the constant declarations you want from the file Adcvbs.inc, located in the C:\Program Files\Common Files\System\MSADC folder.

Remarks

If ExecuteOptions is set to adcExecAsync, then this asynchronously executes the next Refresh call on the RDS.DataControl object’s Recordset.

If you try to call Reset, Refresh, SubmitChanges, CancelUpdate, or Recordset while another asynchronous operation is executing that might change the RDS.DataControl object's Recordset, an error occurs.

If an error occurs during an asynchronous operation, the RDS.DataControl object’s ReadyState value changes from adcReadyStateLoaded to adcReadyStateComplete, and the Recordset property value remains Nothing.


FetchOptions Property (RDS)

Sets or returns the type of asynchronous fetching.

Settings

The FetchOptions property can be any of the following values.

Constant | Description
adcFetchUpFront | All the records of the Recordset are fetched before control is returned to the application. The complete Recordset is fetched before the application is allowed to do anything with it.
adcFetchBackground | Control can return to the application as soon as the first batch of records has been fetched. A subsequent read of the Recordset that attempts to access a record not fetched in the first batch will be delayed until the sought record is actually fetched, at which time control returns to the application.
adcFetchAsync | Default. Control returns immediately to the application while records are fetched in the background. If the application attempts to read a record that hasn't yet been fetched, the record closest to the sought record will be read and control will return immediately, indicating that the current end of the Recordset has been reached. For example, a call to MoveLast will move the current record position to the last record actually fetched, even though more records will continue to populate the Recordset.

Note Each client-side executable file that uses these constants must provide declarations for them. You can cut and paste the constant declarations you want from the file Adcvbs.inc, located in the C:\Program Files\Common Files\System\MSADC folder.

Remarks

In a Web application, you will usually want to use adcFetchAsync (the default value), because it provides better performance. In a compiled client application, you will usually want to use adcFetchBackground.


Filter Property (ADO)

Indicates a filter for data in a Recordset.

Settings and Return Values

Sets or returns a Variant value, which can contain one of the following:

  • Criteria string—a string made up of one or more individual clauses concatenated with AND or OR operators.

  • Array of bookmarks—an array of unique bookmark values that point to records in the Recordset object.

  • One of the following FilterGroupEnum values.
    Constant | Description
    adFilterNone | Removes the current filter and restores all records to view.
    adFilterPendingRecords | Allows you to view only records that have changed but have not yet been sent to the server. Applicable only for batch update mode.
    adFilterAffectedRecords | Allows you to view only records affected by the last Delete, Resync, UpdateBatch, or CancelBatch call.
    adFilterFetchedRecords | Allows you to view records in the current cache—that is, the results of the last call to retrieve records from the database.
    adFilterConflictingRecords | Allows you to view the records that failed the last batch update attempt.

Remarks

Use the Filter property to selectively screen out records in a Recordset object. The filtered Recordset becomes the current cursor. This affects other properties such as AbsolutePosition, AbsolutePage, RecordCount, and PageCount that return values based on the current cursor, because setting the Filter property to a specific value will move the current record to the first record that satisfies the new value.

The criteria string is made up of clauses in the form FieldName-Operator-Value (for example, "LastName = 'Smith'"). You can create compound clauses by concatenating individual clauses with AND (for example, "LastName = 'Smith' AND FirstName = 'John'") or OR (for example, "LastName = 'Smith' OR LastName = 'Jones'"). Use the following guidelines for criteria strings:

  • FieldName must be a valid field name from the Recordset. If the field name contains spaces, you must enclose the name in square brackets.

  • Operator must be one of the following: <, >, <=, >=, <>, =, or LIKE.

  • Value is the value with which you will compare the field values (for example, 'Smith', #8/24/95#, 12.345 or $50.00). Use single quotes with strings and pound signs (#) with dates. For numbers, you can use decimal points, dollar signs, and scientific notation. If Operator is LIKE, Value can use wildcards. Only the asterisk (*) and percent sign (%) wild cards are allowed, and they must be the last character in the string. Value cannot be Null.

  • There is no precedence between AND and OR. Clauses can be grouped within parentheses. However, you cannot group clauses joined by an OR and then join the group to another clause with an AND, like this:
    (LastName = 'Smith' OR LastName = 'Jones') AND FirstName = 'John'

  •
Instead, you would construct this filter as
    (LastName = 'Smith' AND FirstName = 'John') OR (LastName = 'Jones' AND FirstName = 'John')

    •

  •
In a LIKE clause, you can use a wildcard at the beginning and end of the pattern (for example, LastName Like '*mit*'), or only at the end of the pattern (for example, LastName Like 'Smit*').
    •

The filter constants make it easier to resolve individual record conflicts during batch update mode by allowing you to view, for example, only those records that were affected during the last UpdateBatch method call.

Setting the Filter property itself may fail because of a conflict with the underlying data (for example, a record has already been deleted by another user); in such a case, the provider returns warnings to the Errors collection but does not halt program execution. A run-time error occurs only if there are conflicts on all the requested records. Use the Status property to locate records with conflicts.

Setting the Filter property to a zero-length string ("") has the same effect as using the adFilterNone constant.

Whenever the Filter property is set, the current record position moves to the first record in the filtered subset of records in the Recordset. Similarly, when the Filter property is cleared, the current record position moves to the first record in the Recordset.

See the Bookmark property for an explanation of bookmark values from which you can build an array to use with the Filter property.


FilterColumn Property (RDS)

Sets or returns the column on which to evaluate the filter criteria.

Syntax

DataControl.FilterColumn = String

Parameters

DataControl An object variable that represents an RDS.DataControl object.

String A String value specifying the column on which to evaluate the filter criteria. The filter criteria are specified in the FilterCriterion property.

Remarks

The SortColumn, SortDirection, FilterValue, FilterCriterion, and FilterColumn properties provide sorting and filtering functionality on the client-side cache. The sorting functionality orders records by values from one column. The filtering functionality displays a subset of records based on find criteria, while the full Recordset is maintained in the cache. The Reset method will execute the criteria and replace the current Recordset with a read-only Recordset.


FilterCriterion Property (RDS)

Sets or returns which evaluation operator to use in the filter value.

Syntax

DataControl.FilterCriterion = String

Parameters

DataControl An object variable that represents an RDS.DataControl object.

String A String value that specifies the evaluation operator of the FilterValue to the records. Can be any one of the following: <, <=, >, >=, =, or <>.

Remarks

The SortColumn, SortDirection, FilterValue, FilterCriterion, and FilterColumn properties provide sorting and filtering functionality on the client-side cache. The sorting functionality orders records by values from one column. The filtering functionality displays a subset of records based on find criteria, while the full Recordset is maintained in the cache. The Reset method will execute the criteria and replace the current Recordset with a read-only Recordset.

The "!=" operator is invalid for FilterCriterion; instead, use "<>".

If both the filter and sort properties are set and you call the Reset method, the rowset is first filtered and then it is sorted. For ascending sorts, the NULLs are at the top; for descending sorts, NULLs are at the bottom (ascending is default behavior).


FilterValue Property (RDS)

Sets or returns the value with which to filter records.

Syntax

DataControl.FilterValue = String

Parameters

DataControl An object variable that represents an RDS.DataControl object.

String A String value that represents a data value with which to filter records (for example, 'Programmer' or 125).

Remarks

The SortColumn, SortDirection, FilterValue, FilterCriterion, and FilterColumn properties provide sorting and filtering functionality on the client-side cache. The sorting functionality orders records by values from one column. The filtering functionality displays a subset of records based on find criteria, while the full Recordset is maintained in the cache. The Reset method will execute the criteria and replace the current Recordset with a read-only Recordset.


Handler Property (RDS)

Sets or returns a string containing the name of a server-side customization program (handler) that extends the functionality of the RDSServer.DataFactory, and any parameters used by the handler, all separated by commas (",").

Syntax

DataControl.Handler = String

Parameters

DataControl An object variable that represents an RDS.DataControl object.

String A String value that contains the name of the handler and any parameters, all separated by commas (for example, "handlerName,parm1,parm2,...,parm N").

Remarks

The functionality this property supports is called customization. Support for customization requires setting the CursorLocation property to adUseClient.

The name of the handler and its parameters, if any, are separated by commas (","). Unpredictable behavior will result if a semicolon (";") appears anywhere within String. You can write your own handler, provided it supports the IDataFactoryHandler interface.

The name of the default handler is MSDFMAP.Handler, and its default parameter is a customization file named MSDFMAP.INI. Use this property to invoke alternate customization files created by your server administrator.

The alternative to setting the Handler property is to specify a handler and parameters in the ConnectionString property; that is, "Handler=handlerName,parm1,parm2,...;".


InternetTimeout Property (RDS)

Indicates the number of milliseconds to wait before a request times out.

Settings and Return Values

Sets or returns a Long value.

Remarks

This property applies only to requests sent with the HTTP or HTTPS protocols.

Requests in a three-tier environment can take several minutes to execute. Use this property to specify additional time for long-running requests.


IsolationLevel Property (ADO)

Indicates the level of isolation for a Connection object.

Settings and Return Values

Sets or returns one of the following IsolationLevelEnum values.

Constant | Description
adXactUnspecified | Indicates that the provider is using a different IsolationLevel than specified, but that the level cannot be determined.
adXactChaos | Default. Indicates that you cannot overwrite pending changes from more highly isolated transactions.
adXactBrowse | Indicates that from one transaction you can view uncommitted changes in other transactions.
adXactReadUncommitted | Same as adXactBrowse.
adXactCursorStability | Default. Indicates that from one transaction you can view changes in other transactions only after they've been committed.
adXactReadCommitted | Same as adXactCursorStability.
adXactRepeatableRead | Indicates that from one transaction you cannot see changes made in other transactions, but that requerying can bring new recordsets.
adXactIsolated | Indicates that transactions are conducted in isolation of other transactions.
adXactSerializable | Same as adXactIsolated.

Remarks

Use the IsolationLevel property to set the isolation level of a Connection object. The IsolationLevel property is read/write. The setting does not take effect until the next time you call the BeginTrans method. If the level of isolation you request is unavailable, the provider may return the next greater level of isolation.

Remote Data Service Usage When used on a client-side Connection object, the IsolationLevel property can be set only to adXactUnspecified.

Because users are working with disconnected Recordset objects on a client-side cache, there may be multiuser issues. For instance, when two different users try to update the same record, Remote Data Service simply allows the user who updates the record first to "win." The second user's update request will fail with an error.


LockType Property (ADO)

Indicates the type of locks placed on records during editing.

Settings and Return Values

Sets or returns one of the following LockTypeEnum values.

Constant | Description
adLockReadOnly | Default. Read-only—you cannot alter the data.
adLockPessimistic | Pessimistic locking, record by record—the provider does what is necessary to ensure successful editing of the records, usually by locking records at the data source immediately upon editing.
adLockOptimistic | Optimistic locking, record by record—the provider uses optimistic locking, locking records only when you call the Update method.
adLockBatchOptimistic | Optimistic batch updates—required for batch update mode as opposed to immediate update mode.

Remarks

Set the LockType property before opening a Recordset to specify what type of locking the provider should use when opening it. Read the property to return the type of locking in use on an open Recordset object. The LockType property is read/write when the Recordset is closed and read-only when it is open.

Providers may not support all lock types. If a provider cannot support the requested LockType setting, it will substitute another type of locking. To determine the actual locking functionality available in a Recordset object, use the Supports method with adUpdate and adUpdateBatch.

The adLockPessimistic setting is not supported if the CursorLocation property is set to adUseClient. If an unsupported value is set, then no error will result; the closest supported LockType will be used instead.

Remote Data Service Usage When used on a client-side (ADOR) Recordset object, the LockType property can only be set to adLockOptimisticBatch.


MarshalOptions Property (ADO)

Indicates which records are to be marshaled back to the server.

Settings And Return Values

Sets or returns a Long value that can be one of the following constants.

Constant | Description
adMarshalAll | Default. Indicates that all rows are returned to the server.
adMarshalModifiedOnly | Indicates that only modified rows are returned to the server.

Remarks

When using a client-side (ADOR) Recordset, records that have been modified on the client are written back to the middle tier or Web server through a technique called marshaling, the process of packaging and sending interface method parameters across thread or process boundaries. Setting the MarshalOptions property can improve performance when modified remote data is marshaled for updating back to the middle tier or Web server.

Remote Data Service Usage This property is used only on a client-side (ADOR) Recordset.


MaxRecords Property (ADO)

Indicates the maximum number of records to return to a Recordset from a query.

Settings and Return Values

Sets or returns a Long value. Default is zero (no limit).

Remarks

Use the MaxRecords property to limit the number of records the provider returns from the data source. The default setting of this property is zero, which means the provider returns all requested records. The MaxRecords property is read/write when the Recordset is closed and read-only when it is open.


Mode Property (ADO)

Indicates the available permissions for modifying data in a Connection.

Settings and Return Values

Sets or returns one of the following ConnectModeEnum values.

Constant | Description
adModeUnknown | Default. Indicates that the permissions have not yet been set or cannot be determined.
adModeRead | Indicates read-only permissions.
adModeWrite | Indicates write-only permissions.
adModeReadWrite | Indicates read/write permissions.
adModeShareDenyRead | Prevents others from opening connection with read permissions.
adModeShareDenyWrite | Prevents others from opening connection with write permissions.
adModeShareExclusive | Prevents others from opening connection.
adModeShareDenyNone | Prevents others from opening connection with any permissions.

Remarks

Use the Mode property to set or return the access permissions in use by the provider on the current connection. You can set the Mode property only when the Connection object is closed.

Remote Data Service Usage When used on a client-side Connection object, the Mode property can only be set to adModeUnknown.


Name Property (ADO)

Indicates the name of an object.

Settings and Return Values

Sets or returns a String value. The value is read/write on a Command or Parameter object and read-only on a Property or Field object.

Remarks

Use the Name property to assign a name to or retrieve the name of a Command, Field, Parameter, or Property object.

For Parameter objects not yet appended to the Parameters collection, the Name property is read/write. For appended Parameter objects and all other objects, the Name property is read-only. Names do not have to be unique within a collection.

You can retrieve the Name property of an object by an ordinal reference, after which you can refer to the object directly by name. For example, if rstMain.Properties(20).Name yields Updatability, you can subsequently refer to this property as rstMain.Properties("Updatability").


NativeError Property (ADO)

Indicates the provider-specific error code for a given Error object.

Return Value

Returns a Long value.

Remarks

Use the NativeError property to retrieve the database-specific error information for a particular Error object. For example, when using the Microsoft ODBC Provider for OLE DB with a Microsoft® SQL Server™ database, native error codes that originate from SQL Server pass through ODBC and the ODBC Provider to the ADO NativeError property.


Number Property (ADO)

Indicates the number that uniquely identifies an Error object.

Return Value

Returns a Long value.

Remarks

Use the Number property to determine which error occurred. The value of the property is a unique number that corresponds to the error condition.


NumericScale Property (ADO)

Indicates the scale of numeric values in a Parameter or Field object.

Settings and Return Values

Sets or returns a Byte value, indicating the number of decimal places to which numeric values will be resolved.

Remarks

Use the NumericScale property to determine how many digits to the right of the decimal point will be used to represent values for a numeric Parameter or Field object.

For Parameter objects, the NumericScale property is read/write. For Field objects, the NumericScale property is read-only.


Optimize Property (RDS)

Optimize Property (ADO)

Indicates whether an index should be created on this field.

Settings and Return Values

Sets or returns a Boolean value.

Remarks

An index can improve the performance of operations that find or sort values in a Recordset. The index is internal to ADO—you cannot explicitly access or use it in your application.

The Optimize property is "dynamic"; it is not a part of the Field object interface. It exists only in a Field object's Properties collection, provided that you set the CursorLocation property to adUseClient.

To create an index on a field, set the Optimize property to True. To delete the index, set this property to False. If some operation implicitly creates an index on this field, then the operation will set the Optimize property to True.

Usage

Recordset   rs = New ADOB.Recordset
Field       f = New ADODB.Field
rs.CursorLocation = adUseClient   'Enable index creation
rs.Open ...
set f = rs.Fields(0)
f.Properties("Optimize") = TRUE   'Create an index
f.Properties("Optimize") = FALSE   'Delete an index


OriginalValue Property (ADO)

Indicates the value of a Field that existed in the record before any changes were made.

Return Value

Returns a Variant value.

Remarks

Use the OriginalValue property to return the original field value for a field from the current record.

In immediate update mode (the provider writes changes to the underlying data source once you call the Update method), the OriginalValue property returns the field value that existed prior to any changes (that is, since the last Update method call). This is the same value that the CancelUpdate method uses to replace the Value property.

In batch update mode (the provider caches multiple changes and writes them to the underlying data source only when you call the UpdateBatch method), the OriginalValue property returns the field value that existed prior to any changes (that is, since the last UpdateBatch method call). This is the same value that the CancelBatch method uses to replace the Value property. When you use this property with the UnderlyingValue property, you can resolve conflicts that arise from batch updates.


PageCount Property (ADO)

Indicates how many pages of data the Recordset object contains.

Return Value

Returns a Long value.

Remarks

Use the PageCount property to determine how many pages of data are in the Recordset object. Pages are groups of records whose size equals the PageSize property setting. Even if the last page is incomplete, because there are fewer records than the PageSize value, it counts as an additional page in the PageCount value. If the Recordset object does not support this property, the value will be -1 to indicate that the PageCount is indeterminable.

See the PageSize and AbsolutePage properties for more on page functionality.


PageSize Property (ADO)

Indicates how many records constitute one page in the Recordset.

Settings and Return Values

Sets or returns a Long value, indicating how many records are on a page. Default is 10.

Remarks

Use the PageSize property to determine how many records make up a logical page of data. Establishing a page size allows you to use the AbsolutePage property to move to the first record of a particular page. This is useful in Web-server scenarios when you want to allow the user to page through data, viewing a certain number of records at a time.

This property can be set at any time, and its value will be used for calculating the location of the first record of a particular page.


Precision Property (ADO)

Indicates the degree of precision for numeric values in a Parameter object or for numeric Field objects.

Settings and Return Values

Sets or returns a Byte value, indicating the maximum total number of digits used to represent values. The value is read/write on a Parameter object and read-only on a Field object.

Remarks

Use the Precision property to determine the maximum number of digits used to represent values for a numeric Parameter or Field object.


Prepared Property (ADO)

Indicates whether or not to save a compiled version of a command before execution.

Settings and Return Values

Sets or returns a Boolean value.

Remarks

Use the Prepared property to have the provider save a prepared (or compiled) version of the query specified in the CommandText property before a Command object's first execution. This may slow a command's first execution, but once the provider compiles a command, the provider will use the compiled version of the command for any subsequent executions, which will result in improved performance.

If the property is False, the provider will execute the Command object directly without creating a compiled version.

If the provider does not support command preparation, it may return an error as soon as this property is set to True. If it does not return an error, it simply ignores the request to prepare the command and sets the Prepared property to False.


Provider Property (ADO)

Indicates the name of the provider for a Connection object.

Settings and Return Values

Sets or returns a String value.

Remarks

Use the Provider property to set or return the name of the provider for a connection. This property can also be set by the contents of the ConnectionString property or the ConnectionString argument of the Open method; however, specifying a provider in more than one place while calling the Open method can have unpredictable results. If no provider is specified, the property will default to MSDASQL (Microsoft OLE DB Provider for ODBC).

The Provider property is read/write when the connection is closed and read-only when it is open. The setting does not take effect until you either open the Connection object or access the Properties collection of the Connection object. If the setting is invalid, an error occurs.


ReadyState Property (RDS)

Reflects the progress of an RDS.DataControl object as it fetches data into its Recordset object.

Settings

The ReadyState property can have one of the following values.

Value | Description
adcReadyStateLoaded | The current query is still executing and no rows have been fetched. The RDS.DataControl object's Recordset is not available for use.
adcReadyStateInteractive | An initial set of rows retrieved by the current query have been stored in the RDS.DataControl object's Recordset and are available for use. The remaining rows are still being fetched.
adcReadyStateComplete | All rows retrieved by the current query have been stored in the RDS.DataControl object's Recordset and are available for use. This state will also exist if an operation aborted due to an error, or if the Recordset object is not initialized.

Note Each client-side executable file that uses these constants must provide declarations for them. You can cut and paste the constant declarations you want from the file Adcvbs.inc, located in the C:\Program Files\Common Files\System\MSADC folder.

Remarks

Use the onReadyStateChange event method to monitor changes in the ReadyStateChange property during an asynchronous query operation. This is more efficient than periodically checking the value of the property.

If an error occurs during an asynchronous operation, the ReadyState property changes to adcReadyStateComplete, the State property changes from adStateExecuting to adStateClosed, and the Recordset object Value property remains Nothing.


RecordCount Property (ADO)

Indicates the current number of records in a Recordset object.

Return Value

Returns a Long value.

Remarks

Use the RecordCount property to find out how many records are in a Recordset object. The property returns -1 when ADO cannot determine the number of records. Reading the RecordCount property on a closed Recordset causes an error.

If the Recordset object supports approximate positioning or bookmarks—that is, Supports (adApproxPosition) or Supports (adBookmark), respectively, returns True—this value will be the exact number of records in the Recordset regardless of whether it has been fully populated. If the Recordset object does not support approximate positioning, this property may be a significant drain on resources because all records will have to be retrieved and counted to return an accurate RecordCount value.


Recordset, SourceRecordset Properties (RDS)

The SourceRecordset and Recordset properties of the RDS.DataControl indicate the ADOR.Recordset object that is returned from a custom business object.

You can set the SourceRecordset property or read the Recordset property at run time in scripting code (for instance, VBScript).

Syntax

DataControl.SourceRecordset = Recordset

Recordset = DataControl.Recordset

Parameters

DataControl An object variable that represents an RDS.DataControl object.

Recordset An object variable that represents an ADOR.Recordset object.

Remarks

SourceRecordset is a write-only property, in contrast to the Recordset property, which is a read-only property.

You can set the SourceRecordset property to a Recordset returned from a custom business object.

These properties allow an application to handle the binding process by means of a custom process. They receive a rowset wrapped in a Recordset so that you can interact directly with the Recordset, performing actions such as setting properties or iterating through the Recordset.


Server Property (RDS)

Sets or returns the Internet Information Server (IIS) name and communication protocol.

You can set the Server property at design time in the RDS.DataControl object's OBJECT tags, or at run time in scripting code (for example, VBScript).

Syntax

Protocol | Design-time syntax
HTTP | <PARAM NAME="Server" VALUE="http://awebsrvr:port">
HTTPS | <PARAM NAME="Server" VALUE="https://awebsrvr:port">
DCOM | <PARAM NAME="Server" VALUE="machinename">
In-process | <PARAM NAME="Server" VALUE="">

Protocol | Run-time syntax
HTTP | DataControl.Server="https://awebsrvr:port"
HTTPS | DataControl.Server="https://awebsrvr:port"
DCOM | DataControl.Server="machinename"
In-process | DataControl.Server=""

Part | Description
Awebsrvr or machinename | A String that contains a valid Internet or intranet path and server name.
Port | Optional. A port that is used to connect to an IIS server. The port number is set in Internet Explorer (on the View menu, click Options, and then select the Connection tab) or in IIS.
DataControl | An object variable that represents an RDS.DataControl object.

Remarks

The server location is where the server-side objects are created (as opposed to where the data is located, if they differ).


Size Property (ADO)

Indicates the maximum size, in bytes or characters, of a Parameter object.

Settings and Return Values

Sets or returns a Long value that indicates the maximum size in bytes or characters of a value in a Parameter object.

Remarks

Use the Size property to determine the maximum size for values written to or read from the Value property of a Parameter object. The Size property is read/write.

If you specify a variable-length data type for a Parameter object (for example, any String type, such as adVarChar), you must set the object's Size property before appending it to the Parameters collection; otherwise an error occurs.

If you have already appended the Parameter object to the Parameters collection of a Command object and you change its type to a variable-length data type, you must set the Parameter object's Size property before executing the Command object; otherwise an error occurs.

If you use the Refresh method to obtain parameter information from the provider and it returns one or more variable-length data type Parameter objects, ADO may allocate memory for the parameters based on their maximum potential size, which could cause an error during execution. To prevent an error, you should explicitly set the Size property for these parameters before executing the command.


Sort Property (ADO)

Specifies one or more field names the Recordset is sorted on, and whether each field is sorted in ascending or descending order.

Settings and Return Values

Sets or returns a String of comma-separated field names to sort on, where each name is a Field in the Recordset, and is optionally followed by a blank and the keyword ASCENDING or DESCENDING, which specifies the field sort order.

Remarks

The data is not physically rearranged, but is simply accessed in the sorted order.

A temporary index will be created for each field specified in the Sort property if the CursorLocation property is set to adUseClient and an index does not already exist.

Setting the Sort property to an empty string will reset the rows to their original order and delete temporary indexes. Existing indexes will not be deleted.


SortColumn Property (RDS)

Sets or returns which column to sort the records by.

Syntax

DataControl.SortColumn = String

Parameters

DataControl An object variable that represents an RDS.DataControl object.

String A String value that represents the name or alias of the column to sort the records by.

Remarks

The SortColumn, SortDirection, FilterValue, FilterCriterion, and FilterColumn properties provide sorting and filtering functionality on the client-side cache. The sorting functionality orders records by values from one column. The filtering functionality displays a subset of records based on find criteria, while the full Recordset is maintained in the cache. The Reset method will execute the criteria and replace the current Recordset with a read-only Recordset.

To sort on a Recordset, you must first save any pending changes. If you are using the RDS.DataControl, you can use the SubmitChanges method. For example, if your RDS.DataControl is named ADC1, your code would be ADC1.SubmitChanges. If you are using an ADO Recordset, you can use its UpdateBatch method. Using UpdateBatch is the recommended method for Recordset objects created with the CreateRecordset method. For example, your code could be myRS.UpdateBatch or ADC1.Recordset.UpdateBatch.


SortDirection Property (RDS)

Sets or returns a Boolean value that indicates whether a sort order is ascending or descending.

Syntax

DataControl.SortDirection = value

Parameters

DataControl An object variable that represents an RDS.DataControl object.

Value A Boolean value that can set or return one of the following values:

  • True—Ascending order

  • False—Descending order

Remarks

The SortColumn, SortDirection, FilterValue, FilterCriterion, and FilterColumn properties provide sorting and filtering functionality on the client-side cache. The sorting functionality orders records by values from one column. The filtering functionality displays a subset of records based on find criteria, while the full Recordset is maintained in the cache. The Reset method will execute the criteria and replace the current Recordset with a read-only Recordset.


Source Property (ADO Error)

Indicates the name of the object or application that originally generated an error.

Return Value

Returns a String value.

Remarks

Use the Source property on an Error object to determine the name of the object or application that originally generated an error. This could be the object's class name or programmatic ID. For errors in ADODB, the property value will be ADODB.ObjectName, where ObjectName is the name of the object that triggered the error. The Source property is read-only for Error objects.

Based on the error documentation from the Source, Number, and Description properties of Error objects, you can write code that will handle the error appropriately.


Source Property (ADO Recordset)

Indicates the source for the data in a Recordset object (Command object, SQL statement, table name, or stored procedure).

Settings and Return Values

Sets a String value or Command object reference; returns only a String value.

Remarks

Use the Source property to specify a data source for a Recordset object using one of the following: a Command object variable, an SQL statement, a stored procedure, or a table name. The Source property is read/write for closed Recordset objects and read-only for open Recordset objects.

If you set the Source property to a Command object, the ActiveConnection property of the Recordset object will inherit the value of the ActiveConnection property for the specified Command object. However, reading the Source property does not return a Command object; instead, it returns the CommandText property of the Command object to which you set the Source property.

If the Source property is an SQL statement, a stored procedure, or a table name, you can optimize performance by passing the appropriate Options argument with the Open method call.


SQL Property (RDS)

Sets or returns the query string used to retrieve the Recordset.

You can set the SQL property at design time in the RDS.DataControl object's OBJECT tags, or at run time in scripting code (for instance, VBScript).

Syntax

Design time: <PARAM NAME="SQL" VALUE="QueryString">

Run time: DataControl.SQL = "QueryString"

Parameters

QueryString A String containing a valid SQL data request.

DataControl An object variable that represents an RDS.DataControl object.

Remarks

In general, this is an SQL statement (using the dialect of the database server), such as "Select * from NewTitles". To ensure that records are matched and updated accurately, an updatable query must contain a field other than a Long Binary field or a computed field.

The SQL property is optional if a custom server-side business object retrieves the data for the client.


SQLState Property (ADO)

Indicates the SQL state for a given Error object.

Return Value

Returns a five-character String that follows the ANSI SQL standard.

Remarks

Use the SQLState property to read the five-character error code that the provider returns when an error occurs during the processing of a SQL statement. For example, when using the Microsoft OLE DB Provider for ODBC with a Microsoft® SQL Server™ database, SQL state error codes originate from ODBC based either on errors specific to ODBC or on errors that originate from Microsoft SQL Server and are then mapped to ODBC errors. These error codes are documented in the ANSI SQL standard, but may be implemented differently by different data sources.


State Property (ADO)

Describes for all applicable objects whether the state of the object is open or closed.

Describes for a Recordset object executing an asynchronous method, whether the current state of the object is connecting, executing, or fetching.

Return Value

Returns a Long value that can be one of the following constants.

Constant | Description
adStateClosed | Default. Indicates that the object is closed.
adStateOpen | Indicates that the object is open.
adStateConnecting | Indicates that the Recordset object is connecting.
adStateExecuting | Indicates that the Recordset object is executing a command.
adStateFetching | Indicates that the rows of the Recordset object are being fetched.

Remarks

You can use the State property to determine the current state of a given object at any time. This property is read-only.

The Recordset object’s State property can have a combination of values. For example, if a statement is executing, this property will have a combined value of adStateOpen and adStateExecuting.


Status Property (ADO)

Indicates the status of the current record with respect to batch updates or other bulk operations.

Return Value

Returns a sum of one or more of the following RecordStatusEnum values.

Constant | Description
adRecOK | The record was successfully updated.
adRecNew | The record is new.
adRecModified | The record was modified.
adRecDeleted | The record was deleted.
adRecUnmodified | The record was not modified.
adRecInvalid | The record was not saved because its bookmark is invalid.
adRecMultipleChanges | The record was not saved because it would have affected multiple records.
adRecPendingChanges | The record was not saved because it refers to a pending insert.
adRecCanceled | The record was not saved because the operation was canceled.
adRecCantRelease | The new record was not saved because of existing record locks.
adRecConcurrencyViolation | The record was not saved because optimistic concurrency was in use.
adRecIntegrityViolation | The record was not saved because the user violated integrity constraints.
adRecMaxChangesExceeded | The record was not saved because there were too many pending changes.
adRecObjectOpen | The record was not saved because of a conflict with an open storage object.
adRecOutOfMemory | The record was not saved because the computer has run out of memory.
adRecPermissionDenied | The record was not saved because the user has insufficient permissions.
adRecSchemaViolation | The record was not saved because it violates the structure of the underlying database.
adRecDBDeleted | The record has already been deleted from the data source.

Remarks

Use the Status property to see what changes are pending for records modified during batch updating. You can also use the Status property to view the status of records that fail during bulk operations, such as when you call the Resync, UpdateBatch, or CancelBatch methods on a Recordset object, or set the Filter property on a Recordset object to an array of bookmarks. With this property, you can determine how a given record failed and resolve it accordingly.


StayInSync Property (ADO)

Indicates, in a hierarchical Recordset object, whether the parent row should change when the set of underlying child records (that is, a chapter) changes.

Settings and Return Values

Sets or returns a Boolean value. If set to True, the parent Recordset object will be updated if the chapter changes; if False, the parent Recordset object will continue to refer to the previous chapter.

Remarks

This property applies to hierarchical recordsets, such as those supported by the MSDataShape provider, and must be set on the parent Recordset before the child Recordset is retrieved. This property simplifies navigating hierarchical recordsets.


Type Property (ADO)

Indicates the operational type or data type of a Parameter, Field, or Property object.

Settings and Return Values

Sets or returns one of the following DataTypeEnum values. The corresponding OLE DB type indicator is shown in parentheses in the description column of the following table. For more information about OLE DB data types, see Chapter 10 and Appendix A of the OLE DB Programmer's Reference.

Constant | Description
adArray | Joined in a logical OR together with another type to indicate that the data is a safe-array of that type (DBTYPE_ARRAY).
adBigInt | An 8-byte signed integer (DBTYPE_I8).
adBinary | A binary value (DBTYPE_BYTES).
adBoolean | A Boolean value (DBTYPE_BOOL).
adByRef | Joined in a logical OR together with another type to indicate that the data is a pointer to data of the other type (DBTYPE_BYREF).
adBSTR | A null-terminated character string (Unicode) (DBTYPE_BSTR).
adChar | A String value (DBTYPE_STR).
adCurrency | A currency value (DBTYPE_CY). Currency is a fixed-point number with four digits to the right of the decimal point. It is stored in an 8-byte signed integer scaled by 10,000.
adDate | A Date value (DBTYPE_DATE). A date is stored as a Double, the whole part of which is the number of days since December 30, 1899, and the fractional part of which is the fraction of a day.
adDBDate | A date value (yyyymmdd) (DBTYPE_DBDATE).
adDBTime | A time value (hhmmss) (DBTYPE_DBTIME).
adDBTimeStamp | A date-time stamp (yyyymmddhhmmss plus a fraction in billionths) (DBTYPE_DBTIMESTAMP).
adDecimal | An exact numeric value with a fixed precision and scale (DBTYPE_DECIMAL).
adDouble | A double-precision floating point value (DBTYPE_R8).
adEmpty | No value was specified (DBTYPE_EMPTY).
adError | A 32-bit error code (DBTYPE_ERROR).
adGUID | A globally unique identifier (GUID) (DBTYPE_GUID).
adIDispatch | A pointer to an IDispatch interface on an OLE object (DBTYPE_IDISPATCH).
adInteger | A 4-byte signed integer (DBTYPE_I4).
adIUnknown | A pointer to an IUnknown interface on an OLE object (DBTYPE_IUNKNOWN).
adLongVarBinary | A long binary value (Parameter object only).
adLongVarChar | A long String value (Parameter object only).
adLongVarWChar | A long null-terminated string value (Parameter object only).
adNumeric | An exact numeric value with a fixed precision and scale (DBTYPE_NUMERIC).
adSingle | A single-precision floating point value (DBTYPE_R4).
adSmallInt | A 2-byte signed integer (DBTYPE_I2).
adTinyInt | A 1-byte signed integer (DBTYPE_I1).
adUnsignedBigInt | An 8-byte unsigned integer (DBTYPE_UI8).
adUnsignedInt | A 4-byte unsigned integer (DBTYPE_UI4).
adUnsignedSmallInt | A 2-byte unsigned integer (DBTYPE_UI2).
adUnsignedTinyInt | A 1-byte unsigned integer (DBTYPE_UI1).
adUserDefined | A user-defined variable (DBTYPE_UDT).
adVarBinary | A binary value (Parameter object only).
adVarChar | A String value (Parameter object only).
adVariant | An Automation Variant (DBTYPE_VARIANT).
adVector | Joined in a logical OR together with another type to indicate that the data is a DBVECTOR structure, as defined by OLE DB, that contains a count of elements and a pointer to data of the other type (DBTYPE_VECTOR).
adVarWChar | A null-terminated Unicode character string (Parameter object only).
adWChar | A null-terminated Unicode character string (DBTYPE_WSTR).

Remarks

For Parameter objects, the Type property is read/write. For all other objects, the Type property is read-only.


UnderlyingValue Property (ADO)

Indicates a Field object's current value in the database.

Return Value

Returns a Variant value.

Remarks

Use the UnderlyingValue property to return the current field value from the database. The field value in the UnderlyingValue property is the value that is visible to your transaction and may be the result of a recent update by another transaction. This may differ from the OriginalValue property, which reflects the value that was originally returned to the Recordset.

This is similar to using the Resync method, but the UnderlyingValue property returns only the value for a specific field from the current record. This is the same value that the Resync method uses to replace the Value property.

When you use this property with the OriginalValue property, you can resolve conflicts that arise from batch updates.


URL Property (RDS)

Sets or returns the location of a file that contains the persisted (saved) form of a Recordset.

Syntax

Design time: <PARAM NAME="URL" VALUE="URLpath">

Run time: DataControl.URL = "URLpath"

Parameters

URLpath A String containing the URL or path to the persisted file. See Remarks for examples.

DataControl An object variable that represents an RDS.DataControl object.

Usage

Here are some examples of valid URL property values:

FILE://myServer/myPath/filename
HTTP://myServer/myPath/filename
\\myServer/myPath/filename
C:\myPath\filename

Here is an example in Microsoft Visual Basic of a persisted Recordset being restored from a file:

Dim rds AS RDS.DataControl
Set rds.URL = "C:\authors.stm"
rds.Refresh


Value Property (ADO)

Indicates the value assigned to a Field, Parameter, or Property object.

Settings and Return Values

Sets or returns a Variant value. Default value depends on the Type property.

Remarks

Use the Value property to set or return data from Field objects, to set or return parameter values with Parameter objects, or to set or return property settings with Property objects. Whether the Value property is read/write or read-only depends upon numerous factors—see the topics for the respective objects for more information.

ADO allows setting and returning long binary data with the Value property.


Version Property (ADO)

Indicates the ADO version number.

Return Value

Returns a String value.

Remarks

Use the Version property to return the version number of the ADO implementation.

The version of the provider will be available as a dynamic property in the Properties collection.


Using OLE DB Providers with ADO

Much of the power and flexibility of ADO is due to the fact that it can connect to any of several different data providers and still expose the same programming model, regardless of the specific features of any given provider.

However, because each provider is unique, how your application interacts with ADO will vary slightly between different providers. The differences you need to be aware of usually fall into one of three categories:

  • Connection parameters in the ConnectionString property.

  • Command object usage.

  • Provider-specific Recordset behavior.

Provider-specific details in each of these three areas are listed for each of the providers currently available from Microsoft, listed as follows.

Area | Topic
ODBC databases | Microsoft OLE DB Provider for ODBC
Microsoft® Index Server | Microsoft OLE DB Provider for Microsoft Index Server
Microsoft® Active Directory Service | Microsoft OLE DB Provider for Microsoft Active Directory Service
Microsoft® Jet databases | OLE DB Provider for Microsoft Jet
Microsoft® SQL Server | Microsoft SQL Server OLE DB Provider
Oracle databases | Microsoft OLE DB Provider for Oracle

Provider-Specific Dynamic Properties

The Properties collections of the Connection, Command, and Recordset objects include dynamic properties specific to the provider. These properties provide information about functionality specific to the provider beyond the built-in properties ADO supports.

After establishing the connection and creating these objects, use the Refresh method on the object's Properties collection to obtain the provider-specific properties. Refer to the provider documentation and the OLE DB Programmer's Reference for detailed information about these dynamic properties.

See Also For more information about OLE DB providers, see the documentation for Microsoft® OLE DB in the Data Access SDK or visit the Microsoft Data Access Web page at http://www.microsoft.com/data.


Microsoft OLE DB Provider for ODBC

To an ADO or RDS programmer, an ideal world would be one in which every data source exposes an OLE DB interface, so that ADO could call directly into the data source. Although more and more database vendors are implementing OLE DB interfaces, some data sources are not yet exposed this way. However, virtually all DBMS systems in use today can be accessed through ODBC.

The Microsoft® ODBC Provider allows ADO to connect to any ODBC data source. ODBC drivers are available for every major DBMS in use today, including Microsoft® SQL Server™, Microsoft Access (Microsoft Jet database engine), and Microsoft FoxPro®, as well as non-Microsoft database products such as Oracle. The provider is free-threaded and unicode enabled.

The provider supports transactions, although different DBMS engines offer different types of transaction support. For example, Microsoft Access supports nested transactions, up to five levels deep.

This is the default provider for ADO and, when used with Microsoft SQL Server 6.5, all provider-dependent ADO properties and methods are supported, except as noted in the ADO language reference topics.

Connection String Parameters

To connect to this provider, set the Provider= argument of the ConnectionString property to:

MSDASQL

Reading the Provider property will return this string as well.

Because this is the default provider for ADO, if you omit the Provider= parameter from the connection string, ADO will attempt to establish a connection to this provider.

The provider does not support any specific connection parameters in addition to those defined by ADO. However, the provider will pass any non-ADO connection parameters to the ODBC driver manager.

Because you can omit the Provider parameter, you can therefore compose an ADO connection string that is identical to an ODBC connection string for the same data source, using the same parameter names (DRIVER=, DATABASE=, DSN=, and so on), values, and syntax as you would when composing an ODBC connection string. You can connect with or without a predefined data source name (DSN) or FileDSN.

Syntax with a DSN or FileDSN:

"[Provider=MSDASQL;] { DSN=name | FileDSN=filename } ; [DATABASE=database;] UID=user; PWD=password"

Syntax without a DSN (DSN-less connection):

"[Provider=MSDASQL;] DRIVER=driver; SERVER=server; DATABASE=database; UID=user; PWD=password"

If you use a DSN or FileDSN, it must be defined through the ODBC Administrator in the Windows Control Panel. As an alternative to setting a DSN, you can specify the ODBC driver (DRIVER=), such as "SQLServer," the server name (SERVER=), and the database name (DATABASE=).

You can also specify a user account name (UID=), and the password for the user account (PWD=) in the ODBC-specific parameters or in the standard ADO-defined User ID and Password parameters. If you include both the ADO and the ODBC-specific parameters for these values, the ADO parameters take precedence.

Although a DSN definition already specifies a database, you can specify a DATABASE parameter in addition to a DSN to connect to a different database. This also changes the DSN definition to include the specified database. It is a good idea to always include the DATABASE parameter when you use a DSN. This will ensure that you connect to the proper database because another user may have changed the default database parameter since you last checked the DSN definition.

Command Text

How you use the Command object largely depends on the data source, and what type of query or command statement it will accept.

ODBC does provide a specific syntax for calling stored procedures. For the CommandText property of a Command object, the CommandText argument to the Execute method on a Connection object, or the Source argument to the Open method on a Recordset object, pass in a string having this syntax:

"{ [ ? = ] call procedure [ ( ? [, ? [ , … ]] ) ] }"

Where each ? references an object in the Parameters collection. The first ? references Parameters(0), the next ? references Parameters(1), and so on.

The parameter references are optional and depend on the structure of the stored procedure. If you want to call a stored procedure that defines no parameters, your string would look like this:

"{ call procedure }"

If you have two query parameters, your string would look like this:

"{ call procedure ( ?, ? ) }"

If the stored procedure wants to return a value, the return value is treated as another parameter. If you have no query parameters but you do have a return value, your string would look like this:

"{ ? = call procedure }"

Finally, if you have a return value and two query parameters, your string would look like this:

"{ ? = call procedure ( ?, ? ) }"

Recordset Behavior

The following tables list the standard ADO methods and properties available on a Recordset object opened with this provider.

For more detailed information about Recordset behavior for your provider configuration, run the Supports method and enumerate the Properties collection of the Recordset to determine whether provider-specific dynamic properties are present.

Availability of standard ADO Recordset properties:

Property | ForwardOnly | Dynamic | Keyset | Static
AbsolutePage | not available | not available | read/write | read/write
AbsolutePosition | not available | not available | read/write | read/write
ActiveConnection | read/write | read/write | read/write | read/write
BOF | read-only | read-only | read-only | read-only
Bookmark | not available | not available | read/write | read/write
CacheSize | read/write | read/write | read/write | read/write
CursorLocation | read/write | read/write | read/write | read/write
CursorType | read/write | read/write | read/write | read/write
EditMode | read-only | read-only | read-only | read-only
EOF | read-only | read-only | read-only | read-only
Filter | read/write | read/write | read/write | read/write
LockType | read/write | read/write | read/write | read/write
MarshalOptions | read/write | read/write | read/write | read/write
MaxRecords | read/write | read/write | read/write | read/write
PageCount | not available | not available | read-only | read-only
PageSize | read/write | read/write | read/write | read/write
RecordCount | not available | not available | read-only | read-only
Source | read/write | read/write | read/write | read/write
State | read-only | read-only | read-only | read-only
Status | read-only | read-only | read-only | read-only

The AbsolutePosition and AbsolutePage properties are write-only when ADO is used with version 1.0 of the Microsoft OLE DB Provider for ODBC.

Availability of standard ADO Recordset methods:

Method | ForwardOnly | Dynamic | Keyset | Static
AddNew | Yes | Yes | Yes | Yes
Cancel |  |  |  |
CancelBatch | Yes | Yes | Yes | Yes
CancelUpdate | Yes | Yes | Yes | Yes
Clone | No | No | Yes | Yes
Close | Yes | Yes | Yes | Yes
Delete | Yes | Yes | Yes | Yes
GetRows | Yes | Yes | Yes | Yes
Move | Yes | Yes | Yes | Yes
MoveFirst | Yes | Yes | Yes | Yes
MoveLast | No | Yes | Yes | Yes
MoveNext | Yes | Yes | Yes | Yes
MovePrevious | No | Yes | Yes | Yes
NextRecordset* | Yes | Yes | Yes | Yes
Open | Yes | Yes | Yes | Yes
Requery | Yes | Yes | Yes | Yes
Resync | No | No | Yes | Yes
Supports | Yes | Yes | Yes | Yes
Update | Yes | Yes | Yes | Yes
UpdateBatch | Yes | Yes | Yes | Yes

*Not supported for Microsoft Access databases.

See Also For specific implementation details and functional information about the Microsoft OLE DB Provider for ODBC, consult the documentation for Microsoft OLE DB Provider for ODBC and the Microsoft OLE DB Programmer's Reference, available in the Data Access SDK. You can also see the Data Access Web page at http://www.microsoft.com/data.


Microsoft OLE DB Provider for Microsoft Index Server

The Microsoft OLE DB Provider for Microsoft Index Server provides programmatic read-only access to file system and Web data indexed by Microsoft® Index Server 2.0. ADO applications can issue SQL queries to retrieve content and file property information.

The provider is free-threaded and unicode enabled.

Connection String Parameters

To connect to this provider, set the Provider= argument to the ConnectionString property to:

MSIDXS

Reading the Provider property will return this string as well.

Command Text

The Index Server SQL query syntax consists of extensions to the SQL92 SELECT statement and its FROM and WHERE clauses. The results of the query are returned via OLE DB rowsets, which can be consumed by ADO and manipulated as Recordset objects.

You can search for exact words or phrases, or use wildcards to search for patterns or stems of words. The search logic can be based on Boolean decisions, weighted terms' proximity to other words. You can also search by "free text," which finds matches based on meaning, rather than exact words.

The specific command dialect is fully documented in the Microsoft Index Server Reference under "SQL Access to Index Server Data."

The provider does not accept stored procedure calls or simple table names (for example, the CommandType property will always be adCmdText).

Recordset Behavior

The following tables list the features available with a Recordset object opened with this provider. Only the Static cursor type (adOpenStatic) is available.

For more detailed information about Recordset behavior for your provider configuration, run the Supports method and enumerate the Properties collection of the Recordset to determine whether provider-specific dynamic properties are present.

Availability of standard ADO Recordset properties:

Property | Availability
AbsolutePage | read/write
AbsolutePosition | read/write
ActiveConnection | read-only
BOF | read-only
Bookmark* | read/write
CacheSize | read/write
CursorLocation | always adUseServer
CursorType | always adOpenStatic
EditMode | always adEditNone
EOF | read-only
Filter | read/write
LockType | read/write
MarshalOptions | not available
MaxRecords | read/write
PageCount | read-only
PageSize | read/write
RecordCount | read-only
Source | read/write
State | read-only
Status | read-only

*Bookmarks must be enabled on the provider in order for this feature to exist on the Recordset.

Availability of standard ADO Recordset methods:

Method | Available?
AddNew | No
Cancel |
CancelBatch | No
CancelUpdate | No
Clone | Yes
Close | Yes
Delete | No
GetRows | Yes
Move | Yes
MoveFirst | Yes
MoveLast | Yes
MoveNext | Yes
MovePrevious | Yes
NextRecordset | Yes
Open | Yes
Requery | Yes
Resync | Yes
Supports | Yes
Update | No
UpdateBatch | No

See Also For specific implementation details and functional information about the Microsoft OLE DB Provider for Microsoft Index Server, consult the Microsoft OLE DB Programmer's Reference and the Microsoft Index Server documentation. The Microsoft Internet Information Server Web page at http://www.microsoft.com/iis also contains information about Microsoft Index Server.


Microsoft OLE DB Provider for Microsoft Active Directory Service

The Microsoft® Active Directory Service Interfaces (ADSI) Provider allows ADO to connect to heterogeneous directory services through ADSI. This gives ADO applications read-only access to the Microsoft®Windows NT® 4.0 directory services, as well as to any LDAP-compliant directory service and Novell Directory Services. ADSI itself is based on a provider model, so if there is a new provider giving access to another directory, the ADO application will be able to access it seamlessly. The ADSI provider is free-threaded and unicode enabled.

Connection String Parameters

To connect to this provider, set the Provider argument of the ConnectionString property to:

ADSDSOObject

Reading the Provider property will return this string as well.

Command Text

The provider recognizes a four-part command text string in the following syntax:

"Root; Filter; Attributes[; Scope]"

Value | Description
Root | The ADsPath object from which the search is to be started (that is, the root of the search).
Filter | The search filter in the RFC 960 format.
Attributes | A comma-delimited list of attributes to be returned.
Scope Optional. A String that specifies the scope of the search. Can be one of the following:
  • Base—Search only the base object (root of the search).

  • OneLevel—Search only one level.

  • Subtree—Search the entire subtree.

The provider does not accept stored procedure calls or simple table names (for example, the CommandType property will always be adCmdText). See the Active Directory Service Interfaces documentation for a more complete description of the command text elements.

Recordset Behavior

The following tables list the features available on a Recordset object opened with this provider. Only the Static cursor type (adOpenStatic) is available.

For more detailed information about Recordset behavior for your provider configuration, run the Supports method and enumerate the Properties collection of the Recordset to determine whether provider-specific dynamic properties are present.

Availability of standard ADO Recordset properties:

Property | Availability
AbsolutePage | read/write
AbsolutePosition | read/write
ActiveConnection | read-only
BOF | read-only
Bookmark | read/write
CacheSize | read/write
CursorLocation | always adUseServer
CursorType | always adOpenStatic
EditMode | always adEditNone
EOF | read-only
Filter | read/write
LockType | read/write
MarshalOptions | not available
MaxRecords | read/write
PageCount | read-only
PageSize | read/write
RecordCount | read-only
Source | read/write
State | read-only
Status | read-only

Availability of standard ADO Recordset methods:

Method | Available?
AddNew | No
Cancel |
CancelBatch | No
CancelUpdate | No
Clone | Yes
Close | Yes
Delete | No
GetRows | Yes
Move | Yes
MoveFirst | Yes
MoveLast | Yes
MoveNext | Yes
MovePrevious | Yes
NextRecordset | Yes
Open | Yes
Requery | Yes
Resync | Yes
Supports | Yes
Update | No
UpdateBatch | No

See Also For more information about ADSI in general and the specifics of the provider, please refer to the documentation provided in the Active Directory Service Interfaces SDK. You can install the SDK from the ADSI Web page at http://www.microsoft.com/ntserver/info/adsi.htm.


OLE DB Provider for Microsoft Jet

The OLE DB Provider for Microsoft® Jet allows ADO to access Microsoft Jet databases.

Connection String Parameters

To connect to this provider, set the Provider argument of the ConnectionString property to:

Microsoft.Jet.OLEDB.3.51

Reading the Provider property will return this string as well.

The OLE DB Provider for Microsoft Jet supports several provider-specific connection parameters in addition to those defined by ADO. As with all other connection parameters, they can be set via the Connection object's Properties collection or as part of the connection string.

Parameter | Description
Jet OLEDB:System Database | The path and file name for the workgroup information file.
Jet OLEDB:Registry Path | The Windows registry key that contains values for the Microsoft Jet database engine.
Jet OLEDB:Database Password | The database password.

By default, the OLE DB Provider for Microsoft Jet opens Microsoft Jet databases in read/write mode. To open a database in read-only mode, set the Mode property on the ADO Connection object to adModeRead.

Command Object Usage

Command text in the Command object uses the Jet SQL dialect. You can specify row-returning queries, action queries, and table names in the command text; however, stored procedures are not supported and should not be specified.

Recordset Behavior

The Microsoft Jet database engine does not support dynamic cursors. Therefore, the OLE DB Provider for Microsoft Jet does not support the adLockDynamic cursor type. When a dynamic cursor is requested, the provider will return a keyset cursor and reset the CursorType property to indicate the type of Recordset returned. Further, if an updatable Recordset is requested (LockType is adLockOptimistic, adLockBatchOptimistic, or adLockPessimistic) the provider will also return a keyset cursor and reset the CursorType property.

See Also For specific implementation details and functional information about the OLE DB Provider for Microsoft Jet, consult the OLE DB Provider for Microsoft Jet documentation in the Data Access SDK.


Microsoft SQL Server OLE DB Provider

The Microsoft® SQL Server OLE DB Provider, SQLOLEDB, allows ADO to access Microsoft® SQL Server™.

Connection String Parameters

To connect to this provider, set the Provider argument to the ConnectionString property to:

SQLOLEDB

This value can also be set or read using the Provider property.

The provider supports several provider-specific connection parameters in addition to those defined by ADO. As with the ADO connection properties, these provider-specific properties can be set via the Properties collection of a Connection or can be set as part of the ConnectionString.

Parameter | Description
Trusted Connection | User authentication mode. This can be set to True or False. The default value is False. If this property is set to True then SQLOLEDB uses Microsoft® Windows NT® Authentication Mode to authorize user access to the SQL Server database specified by the Location and Datasource property values. If this property is set to False then SQLOLEDB uses Mixed Mode to authorize user access to the SQL Server database. The SQL Server login and password are specified in the User Id and Password properties.
Current Language | A SQL Server language name. Identifies the language used for system message selection and formatting. The language must be installed on the SQL Server or opening the connection will fail.
Network Address | The network address of the SQL Server specified by the Location property.
Network Library | The name of the Net-Library (DLL) used to communicate with the SQL Server. The name should not include the path or the .dll file name extension. The default is provided by the SQL Server client configuration.
Use Procedure for Prepare | SQL Server stored procedure use. Defines the use of SQL Server temporary stored procedures to when Commands are prepared.
Auto Translate | OEM/ANSI character conversion. This property can be set to True or False. The default value is True. If this property is set to True then SQLOLEDB performs OEM/ANSI character conversion when multibyte character strings are retrieved from, or sent to, the SQL Server. If this property is set to False then SQLOLEDB does not perform OEM/ANSI character conversion on multibyte character string data.
Packet Size | A network packet size in bytes. The packet size property value must be between 512 and 32767. The default SQLOLEDB network packet size is 4096.
Application Name | The client application name.
Workstation ID | A string identifying the workstation.

Command Object Usage

SQLOLEDB accepts an amalgam of ODBC, ANSI, and SQL Server-specific Transact-SQL as valid syntax. For example, the following SQL statement uses an ODBC SQL escape sequence to specify the LCASE string function:

SELECT customerid={fn LCASE(CustomerID)} FROM Customers

LCASE returns a character string, converting all uppercase characters to their lowercase equivalents. The ANSI SQL string function LOWER performs the same operation, so the following SQL statement is an ANSI equivalent to the ODBC statement presented above:

SELECT customerid=LOWER(CustomerID) FROM Customers

SQLOLEDB successfully processes either form of the statement when specified as text for a command.

Stored Procedures

When executing an SQL Server stored procedure using an SQLOLEDB command, use the ODBC procedure call escape sequence in the command text. SQLOLEDB then uses the remote procedure call mechanism of SQL Server to optimize command processing. For example, the following ODBC SQL statement is preferred command text over the Transact-SQL form:

ODBC SQL

{call SalesByCategory('Produce', '1995')}

Transact-SQL

EXECUTE SalesByCategory 'Produce', '1995'

Recordset Behavior

SQLOLEDB cannot use SQL Server cursors to support the multiple-rowsets result generated by many commands. If a consumer requests a recordset requiring SQL Server cursor support, an error occurs if the command text used generates more than a single recordset as its result.

Scrollable SQLOLEDB recordsets are supported by SQL Server cursors. SQL Server imposes limitations on cursors that are sensitive to changes made by other users of the database. Specifically, the rows in some cursors cannot be ordered, and attempting to create a rowset using a command containing an SQL ORDER BY clause can fail.

See Also For specific implementation details and functional information about the Microsoft SQL Server OLE DB Provider, consult the Microsoft SQL Server OLE DB Provider documentation in the Data Access SDK.


Microsoft OLE DB Provider for Oracle

The Microsoft Oracle OLE DB Provider allows ADO to access Oracle databases.

Connection String Parameters

To connect to this provider, set the Provider argument to the ConnectionString property to:

MSDAORA

Reading the Provider property will return this string as well.


ADO Tutorial

This tutorial illustrates using the ADO programming model to query and update a data source. First, it describes the steps necessary to accomplish this task. Then the tutorial is repeated in Microsoft® Visual Basic®; Microsoft® Visual C++®, featuring VC++ Extensions; Microsoft® Visual Basic®, Scripting Edition; and Microsoft® Visual J++™, featuring ADO for Windows Foundation Classes (ADO/WFC).

This tutorial is coded in different languages for two reasons:

  • The documentation for ADO assumes the reader codes in Visual Basic. This makes the documentation convenient for Visual Basic programmers, but less useful for programmers who use other languages.

  • If you are uncertain about a particular ADO feature and you know a little of another language, you may be able to resolve your question by looking for the same feature expressed in another language.

How the Tutorial is Presented

This tutorial is based on the ADO programming model. It discusses each step of the programming model individually. In addition, it illustrates each step with a fragment of Visual Basic code. At the end, it restates and integrates the code fragments as a Visual Basic example.

The code example is repeated in other languages, however, without the discussion. Each step in a given programming language tutorial is marked with the corresponding step in the programming model and descriptive tutorial. Use the number of the step to refer to the discussion in the descriptive tutorial.

Because this tutorial consists of several small fragments of code, you cannot execute the code as written.

The ADO programming model is restated below. Use it as a roadmap as you proceed through the tutorial.

ADO Programming Model with Objects

  • Make a connection to a data source (Connection). Optionally, begin a transaction.

  • Optionally, create an object to represent an SQL command (Command).

  • Optionally, specify columns, tables, and values in the SQL command as variable parameters (Parameter).

  • Execute the command (Command, Connection, or Recordset).

  • If the command is row-returning, store the rows in a storage object (Recordset).

  • Optionally, create a view of the storage object so you can sort, filter, and navigate the data (Recordset).

  • Edit the data, either adding, deleting, or changing rows and columns (Recordset).

  • If appropriate, update the data source with changes from the storage object (Recordset).

  • If a transaction was used, accept or reject the changes made during the transaction. End the transaction (Connection).

Next Step 1


Step 1: Open a Connection (ADO Tutorial)

You are Here...

  • Make a connection to a data source.

  • Optionally, create an object to represent an SQL query command.

  • Optionally, specify values in the SQL command as variable parameters.

  • Execute the command. If the command is row-returning, store the rows in a storage object.

  • Optionally, navigate, examine, manipulate, and edit the data.

  • If appropriate, update the data source with changes from the storage object. Optionally, embed the update in a transaction.

  • If you used a transaction, accept or reject the changes made during the transaction. End the transaction.

Discussion

You require a means to establish the conditions necessary to exchange data; that is, a connection. The data source you connect to is specified in a connection string, although the parameters specified in a connection string may differ for each provider and data source.

The main way ADO opens a connection is with the Connection.Open method. Alternatively, you can invoke the shortcut method, Recordset.Open, to both open a connection and issue a command over that connection in one operation. Following is the syntax for each method in Visual Basic:

connection.Open ConnectionString, UserID, Password, OpenOptions
recordset.Open Source, ActiveConnection, CursorType, LockType, Options

It's helpful to compare these two methods to highlight some useful characteristics of ADO method operands in general.

ADO provides several convenient ways to specify an operand. For example, Recordset.Open takes an ActiveConnection operand, which could be the literal string, a variable representing that string, or a Connection object representing an open connection.

Most methods on an object have properties that can provide an argument if a method operand is omitted. In the case of Connection.Open, you could omit the explicit ConnectionString operand and supply the information implicitly by setting the ConnectionString property to "DSN=pubs;uid=sa;pwd=;database=pubs".

Conversely, the uid and pwd keyword operands in a connection string can set the Connection object UserID and Password parameters.

This tutorial invokes the Connection.Open method with an explicit connection string. The data source will be the Open Database Connectivity (ODBC) pubs database, which ships as a test database with Microsoft SQL Server. (The actual location of the data source—such as a local drive or remote server—is specified when you define the Data Source Name (DSN).)

connection.Open "DSN=pubs;uid=sa;pwd=;database=pubs"

Next Step 2


Step 2: Create a Command (ADO Tutorial)

You are Here...

  • Make a connection to a data source.

  • Optionally, create an object to represent an SQL query command.

  • Optionally, specify values in the SQL command as variable parameters.

  • Execute the command. If the command is row-returning, store the rows in a storage object.

  • Optionally, navigate, examine, manipulate, and edit the data.

  • If appropriate, update the data source with changes from the storage object. Optionally, embed the update in a transaction.

  • If a transaction was used, accept or reject the changes made during the transaction. End the transaction.

Discussion

A query command requests that the data source return a Recordset object containing rows of requested information. Commands are typically written in SQL.

  1. As mentioned, operands such as a command string can be represented as:
    • A literal string or a variable that represents the string. This tutorial could query for all the information in the authors table of the pubs database with the command string "SELECT * from authors".

    • An object that represents the command string. In this case, the value of a Command object CommandText property set to the command string.
      Command cmd = New ADODB.Command;
cmd.CommandText = "SELECT * from authors"
  2. Specify a parameterized command string with the '?' placeholder.

    The content of an SQL string is fixed. However, you can create a parameterized command where '?' placeholder substrings can be replaced with parameters when a command is executed.

    You can optimize the performance of parameterized commands with the Prepared property. You can issue them repeatedly, changing only their parameters each time.

    For example, the following command string issues a query for all the authors whose last name is "Ringer":

    Command cmd = New ADODB.Command
cmd.CommandText = "SELECT * from authors WHERE au_lname = ?"
  3. Specify a Parameter object. Append it to the Parameters collection.

    Each '?' placeholder is replaced by the value of a corresponding Parameter object in the Command object Parameters collection. Create a Parameter object with Ringer as the value, then append it to the Parameters collection:

    Parameter prm = New ADODB.Parameter
prm.Name = "au_lname"
prm.Type = adVarChar
prm.Direction = adInput
prm.Size = 40
prm.Value = "Ringer"
cmd.Parameters.Append prm
  4. Specify and append a Parameter object with the CreateParameter method.

    ADO now offers a convenient alternative means to create a Parameter object and append it to the Parameters collection in one step.

    cmd.Parameters.Append cmd.CreateParameter _
"au_lname", adVarChar, adInput, 40, "Ringer"

    However, this tutorial won't use a parameterized command, because you must use the Command.Execute method to substitute the parameters for the ‘?’ placeholders. But that method wouldn't allow us to specify Recordset cursor type and lock options. For that reason, use this code:

    Command cmd = New ADODB.Command;
cmd.CommandText = "SELECT * from authors"

For your information, this is the schema of the authors table:

Column Name | Data Type(length) | Nullable
au_id | ID (11) | no
au_lname | varchar(40) | no
au_fname | varchar(20) | no
phone | char(12) | no
address | varchar(40) | yes
city | varchar(20) | yes
state | char(2) | yes
zip | char(5) | yes
contract | bit | no

Next Step 3


Step 3: Execute the Command (ADO Tutorial)

You are Here...

  • Make a connection to a data source.

  • Optionally, create an object to represent an SQL query command.

  • Optionally, specify values in the SQL command as variable parameters.

  • Execute the command. If the command is row-returning, store the rows in a storage object.

  • Optionally, navigate, examine, manipulate, and edit the data.

  • If appropriate, update the data source with changes from the storage object. Optionally, embed the update in a transaction.

  • If a transaction was used, accept or reject the changes made during the transaction. End the transaction.

Discussion

The three methods that return a Recordset are Connection.Execute, Command.Execute, and Recordset.Open. This is their syntax in Visual Basic:

connection.Execute(CommandText, RecordsAffected, Options)
command.Execute(RecordsAffected, Parameters, Options)
recordset.Open Source, ActiveConnection, CursorType, LockType, Options

These methods are optimized to take advantage of the strengths of their particular objects.

Before you issue a command, you must open a connection. Each method that issues a command represents the connection differently:

  • The Connection.Execute method uses the connection embodied by the Connection object itself.

  • The Command.Execute method uses the Connection object set in its ActiveConnection property.

  • The Recordset.Open method specifies either a connect string or Connection object operand, or uses the Connection object set in its ActiveConnection property.

Another difference is the way the command is specified in the three methods:

  • In the Connection.Execute method, the command is a string.

  • In the Command.Execute method, the command isn't visible—it's specified in the Command.CommandText property. Furthermore, the command can contain parameter symbols (‘?’) which will be replaced by the corresponding parameter in the Parameters VARIANT array argument.

  • In the Recordset.Open method, the command is the Source argument, which can be a string or a Command object.

Each method trades off functionality versus performance:

  • The Execute methods are intended for—but are not limited to—executing commands that don't return data.

  • Both Execute methods return fast but read-only, forward-only Recordset objects.

  • The Command.Execute method allows you to use parameterized commands that can be reused efficiently.

  • On the other hand, the Open method allows you to specify the CursorType (strategy and object used to access the data); and LockType (specify the degree of isolation from other users, and whether the cursor should support updates in immediate or batch modes).

  • We advise you to study these options; they embody much of the functionality of a Recordset.

This tutorial uses a dynamic cursor to batch any changes to the Recordset. For this reason, use the following:

Recordset rs = New ADODB.Recordset
rs.Open cmd, conn, adOpenDymanic, adLockBatchOptimistic

Next Step 4


Step 4: Manipulate the Data (ADO Tutorial)

You are Here...

  • Make a connection to a data source.

  • Optionally, create an object to represent an SQL query command.

  • Optionally, specify values in the SQL command as variable parameters.

  • Execute the command. If the command is row-returning, store the rows in a storage object.

  • Optionally, navigate, examine, manipulate, and edit the data.

  • If appropriate, update the data source with changes from the storage object. Optionally, embed the update in a transaction.

  • If a transaction was used, accept or reject the changes made during the transaction. End the transaction.

Discussion

The bulk of the Recordset object methods and properties are devoted to examining, navigating, and manipulating the rows of Recordset data.

A Recordset can be thought of as an array of rows. The row you can examine and manipulate at any given time is the current row, and your location in the Recordset is the current row position. Every time you move to another row, that row becomes the new current row.

Several methods explicitly move or "navigate" through the Recordset (the Move methods). Some methods (the Find method) do so as a side effect of their operation. In addition, setting certain properties (Bookmark property) can also change your row position.

The Filter property can be applied to control rows you can access (that is, which rows are "visible" to you). The Sort property controls the order in which you navigate the rows of the Recordset.

A Recordset has a Fields collection, which is the set of Field objects that represent each field, or column, in a row. Assign or retrieve the data for a field from the Field object’s Value property. As an option, you can access field data in bulk (the GetRows and Update methods).

In this tutorial, you will:

  • Assume that telephone numbers in the "415" area code with exchanges starting with "5", are changing to the mythical area code "777."

  • Set the Optimize property of the au_lname Field object to improve the performance of sorting and filtering.

  • Sort the Recordset on each author's last name.

  • Filter the Recordset so the only accessible (that is, "visible") rows will be those where the author's area code is "415" and exchange begins with "5".

Use the Move methods to navigate from the beginning of the sorted, filtered Recordset to the end. Stop when the Recordset EOF property indicates you've reached the last row. As you move through the Recordset, display the author's first and last name and the original telephone number, then change the area code in the phone field to "777". (Telephone numbers in the phone field are of the form "aaa xxx-yyyy" where aaa is the area code and xxx is the exchange.)

rs!au_lname.Optimize = TRUE
rs.Sort = "au_lname ASCENDING"
rs.Filter = "phone LIKE '415 5*'"
rs.MoveFirst
Do While Not rs.EOF
   Debug.Print "Name: " & rs!au_fname & " " rs!au_lname & _
      "Phone: " rs!phone & vbCr
   rs!phone = "777" & Mid(rs!phone, 5, 11)
   rs.MoveNext
Loop

Next Step 5


Step 5: Update the Data (ADO Tutorial)

You are Here...

  • Make a connection to a data source.

  • Optionally, create an object to represent an SQL query command.

  • Optionally, specify values in the SQL command as variable parameters.

  • Execute the command. If the command is row-returning, store the rows in a storage object.

  • Optionally, navigate, examine, manipulate, and edit the data.

  • If appropriate, update the data source with changes from the storage object. Optionally, embed the update in a transaction.

  • If a transaction was used, accept or reject the changes made during the transaction. End the transaction.

Discussion

You've just changed the data in several rows of the Recordset. ADO supports two basic concepts for the addition, deletion, and modification of rows of data.

The first notion is that changes aren't immediately made to the Recordset; instead, they are made to an internal copy buffer. If you decide you don't want the changes, then the modifications in the copy buffer are discarded. If decide you want to keep the changes, then the changes in the copy buffer are applied to the Recordset.

The second notion is that changes are either propagated to the data source as soon as you declare the work on a row complete (that is, immediate mode) or else all the changes for a set of rows are collected until you declare that the work for the set is complete (that is, batch mode). These modes are governed by the CursorLocation and LockType properties.

In immediate mode, each invocation of the Update method propagates the changes to the data source. In batch mode, each invocation of Update or movement of the current row position saves the changes to the Recordset, but only the UpdateBatch method propagates the changes to the data source. You opened the Recordset in batch mode, so you'll update in batch mode.

Note There is a convenience form of Update in which you apply a change to a field, or an array of changes to an array of fields, then perform the update, all in one step.

Optionally, you can perform your update in a transaction. In practice, you would use a transaction to ensure that several related operations that depended on each other either all occurred successfully, or else were all canceled. In this case, a transaction isn't really necessary.

Transactions typically allocate and hold limited resources on the data source for long periods of time. For that reason it is advisable that a transaction exist for as brief a period as possible. (That's why this tutorial didn't begin the transaction as soon as you made a connection.)

For the tutorial, bracket your batch update in a transaction:

conn.BeginTrans
rs.UpdateBatch
...

Next Step 6


Step 6: Conclude the Update (ADO Tutorial)

You are Here...

  • Make a connection to a data source.

  • Optionally, create an object to represent an SQL query command.

  • Optionally, specify values in the SQL command as variable parameters.

  • Execute the command. If the command is row-returning, store the rows in a storage object.

  • Optionally, navigate, examine, manipulate, and edit the data.

  • If appropriate, update the data source with changes from the storage object. Optionally, embed the update in a transaction.

  • If a transaction was used, accept or reject the changes made during the transaction. End the transaction.

Discussion

Imagine that the batch update concluded with errors. How you resolve the errors depends on the nature and severity of the error and the logic of your application. However, if the database is shared with other users, one typical error is that someone else modifies the field before you do. This type of error is called a conflict. ADO detects this situation and reports an error.

In this tutorial, this step has two parts: If there are no update errors, commit the transaction. This concludes the update.

If there are errors, they will be trapped in an error-handling routine. Filter the Recordset with the adFilterConflictingRecords constant so only the conflicting rows are visible. The error-resolution strategy is merely to print the author's first and last names (au_fname and au_lname ). Then roll back the transaction, discarding the successful updates. This concludes the update.

...
conn.CommitTrans
...
On Error
rs.Filter = adFilterConflictingRecords
rs.MoveFirst
Do While Not rs.EOF
   Debug.Print "Conflict: Name: " & rs!au_fname " " & rs!au_lname
   rs.MoveNext
Loop
conn.Rollback
Resume Next
...

This is the end of the tutorial.


ADO Tutorial (VB)

Public Sub main()

Dim conn As New ADODB.Connection
Dim cmd As New ADODB.Command
Dim rs As New ADODB.Recordset
' Step 1
conn.Open "DSN=pubs;uid=sa;pwd=;database=pubs"
' Step 2
Set cmd.ActiveConnection = conn
cmd.CommandText = "SELECT * from authors"
' Step 3
rs.CursorLocation = adUseClient
rs.Open cmd, , adOpenStatic, adLockBatchOptimistic
' Step 4
rs!au_lname.Properties("Optimize") = True
rs.Sort = "au_lname"
rs.Filter = "phone LIKE '415 5*'"
rs.MoveFirst
Do While Not rs.EOF
    Debug.Print "Name: " & rs!au_fname & " "; rs!au_lname & _
        "Phone: "; rs!phone & vbCr
    rs!phone = "777" & Mid(rs!phone, 5, 11)
    rs.MoveNext
Loop

' Step 5
conn.BeginTrans

'Step 6, part A
On Error GoTo ConflictHandler
rs.UpdateBatch
On Error GoTo 0

conn.CommitTrans

Exit Sub

'Step 6, part B
ConflictHandler:

rs.Filter = adFilterConflictingRecords
rs.MoveFirst
Do While Not rs.EOF
    Debug.Print "Conflict: Name: " & rs!au_fname; " " & rs!au_lname
    rs.MoveNext
Loop
conn.Rollback
Resume Next

End Sub

This is the end of the Visual Basic tutorial.


ADO Tutorial (VC++)

This tutorial features the new Microsoft® Visual C++® Extensions. The VC++ Extensions eliminate the use of cumbersome VARIANT data types.

This tutorial also uses the #import directive, which converts the ADO typelib into a header file. That header file makes some ADO functionality similar in use and appearance to its equivalent in Microsoft® Visual Basic® .

#define INITGUID
#import "c:\Program Files\Common Files\System\ADO\msado15.dll"
   no_namespace rename("EOF", "EndOfFile")
#include <stdio.h>
#include "icrsint.h"

void dump_com_error(_com_error &e)
   {
   printf("Error\n");
   printf("\a\tCode = %08lx\n", e.Error());
   printf("\a\tCode meaning = %s", e.ErrorMessage());
   _bstr_t bstrSource(e.Source());
   _bstr_t bstrDescription(e.Description());
   printf("\a\tSource = %s\n", (LPCSTR) bstrSource);
   printf("\a\tDescription = %s\n", (LPCSTR) bstrDescription);
   }

class CCustomRs :
   public CADORecordBinding
{
BEGIN_ADO_BINDING(CCustomRs)
   ADO_VARIABLE_LENGTH_BINDING_ENTRY(1, adVarChar, m_szau_lname,
         sizeof(m_szau_lname), lau_lnameStatus, FALSE)
   ADO_VARIABLE_LENGTH_BINDING_ENTRY(2, adVarChar, m_szau_fname,
         sizeof(m_szau_fname), lau_fnameStatus, FALSE)
   ADO_FIXED_LENGTH_BINDING_ENTRY(3, adChar, m_szphone,
         sizeof(m_szphone), lphoneStatus, TRUE)
END_ADO_BINDING()

public:
   CHAR   m_szau_lname[41];
   ULONG   lau_lnameStatus;
   CHAR   m_szau_fname[41];
   ULONG   lau_fnameStatus;
   CHAR   m_szphone[12];
   ULONG   lphoneStatus;
};

VOID   main()
   {
   HRESULT hr;
   IADORecordBinding   *picRs = NULL;

   ::CoInitialize(NULL);

   try
      {
      _ConnectionPtr pConn("ADODB.Connection.1.5");
      _RecordsetPtr pRs("ADODB.Recordset.1.5");
      CCustomRs rs;

// Step 1—Open a connection

      pConn->Open("dsn=pubs;uid=sa;pwd=;");

//Step 2—Create a command

// Step 3—Execute the command

      pRs->Open("select * from authors", pConn,
         adOpenDynamic, adLockOptimistic, adCmdUnknown);

      if (FAILED(hr = pRs->QueryInterface(__uuidof(IADORecordBinding),
            (LPVOID*)&picRs)))
         _com_issue_error(hr);

      if (FAILED(hr = picRs->BindToRecordset(&rs)))
         _com_issue_error(hr);

// Step 4—Manipulate the data

      pRs->Fields("au_lname").Optimize = TRUE;
      pRs->Sort = "au_lname ASCENDING";
      pRs->Filter = "phone LIKE '415 5*";

      pRs->MoveFirst();
      while (VARIANT_FALSE == pRs->EndOfFile)
         {
         printf("\a\tName: %s\t %s\tPhone: %s\n",
            (lau_fnameStatus == adFldOK ? m_szau_fname : ""),
            (lau_lnameStatus == adFldOK ? m_szau_lname): ""),
            (lau_lphoneStatus == adFldOK ? m_szphone): ""));

         if (lphoneStatus == adFldOK)
            lmemcpy(m_szphone, "777", 3);

         if (FAILED(hr = picRs->Update(&rs)))
            _com_issue_error(hr);

      // Change the current row of the Recordset.
      // Recordset data for the new current row will automatically be
      // extracted and placed in the CCustomRs C++ instance variables.

         pRs->MoveNext();
         }
      pRs->Filter = adFilterNone;

// Step 5—Update the data

      pConn->BeginTrans();
      pRs->UpdateBatch();

// Step 6, part A—Conclude the update

      pConn->CommitTrans();
      }
   catch (_com_error &e)
      {
      dump_com_error(e);
      }
   catch (ADODB.Error &e)
      {
      pRS->Filter = adConflictingRecords;
      pRs->MoveFirst();
      while (VARIANT_FALSE == pRs->EndOfFile)
         {
         printf("\a\tConflict: Name = %s\t %s\n",
            (lau_fnameStatus == adFldOK ? m_szau_fname : ""),
            (lau_lnameStatus == adFldOK ? m_szau_lname): ""));
         pRs->MoveNext();
         }

// Step 6, part B—Conclude the update

      pConn->Rollback();
      }

   if (picRs)
      picRs->Release();

   CoUninitialize();
   }

This is the end of the VC++ tutorial.


ADO Tutorial (VJ++)

This tutorial features the new ADO/WFC.

import com.ms.wfc.data.*;

/**
* ADOTutorial:
* Purpose: Demonstrates the usage of Ado in Java.
*          opens a recordset through a command object
*          and illustrates update within a transaction
*/
public class ADOTutorial
{
   public static String strConn = "Driver={SQL Server};SERVER=JDO_ODIN;DATABASE=JetQA;UID=testmod;PWD=testmod;";//odbc type conn string

   public static void main(String args[] )
   {
      try
      {
         Connection conn = new Connection();
         Command cmd = new Command();
         Recordset rs = new Recordset();

         int actErrorNum = 0;
         Field fld;
         AdoProperties fldProps;

//STEP1 : open the connection

         conn.open(strConn);

//STEP 2: Create a command

         cmd.setActiveConnection(conn);
         cmd.setCommandText("SELECT * from authors");

//Step 3- Open the recordset with the source as a command object

         rs.setCursorLocation(AdoEnums.CursorLocation.CLIENT);
         rs.setCursorType(AdoEnums.CursorType.DYNAMIC);
         rs.setLockType(AdoEnums.LockType.BATCHOPTIMISTIC);
         rs.open (cmd);

//STEP 4 - Manipulate the data

         fldProps  = rs.getField("au_lname").getProperties();

                           fldProps.getItem("Optimize").setBoolean(true);

         rs.setSort("au_lname");

         rs.setFilter("phone like '415*'");

         rs.moveFirst();

         while ( !rs.getEOF())

         {
            StringBuffer strBuf = new StringBuffer();
            System.out.println( " Name: " + rs.getField("au_fname").getString() +
               "  " + rs.getField("au_lname").getString() +
               "   Phone : " + rs.getField("phone").getString() );

            //change the area code 415 to 779 for the field
            fld =  rs.getField("phone");

            strBuf.append( fld.getString());

            strBuf.setCharAt(0, '7');
            strBuf.setCharAt(1, '7');
            strBuf.setCharAt(2,  '9');

            //set the field to the new value
            fld.setString(strBuf.toString());

            rs.moveNext();

         }

// STEP5 - update the set field values

         conn.beginTrans();

                 //STEP6 Part A: Conclude the Update
         try
         {

            rs.updateBatch();
            conn.commitTrans();

         }

//STEP6: Conclude the Update

         catch(com.ms.wfc.data.AdoException ex)
         {

           //error has occured we have to rollback
           //transaction
            rs.setFilter(new Integer                        (AdoEnums.FilterGroup.CONFLICTINGRECORDS));
            rs.moveFirst();

            while(!rs.getEOF())
            {
               //print conflicting records
               System.out.println(" Conflict : Name : "+ rs.getField("au_fname").getString() + " " +
                  rs.getField("au_lname").getString() );

               rs.moveNext();
            }
            conn.rollbackTrans();
         }
             System.out.println("type any character to continue...");
         System.in.read();

      }
      catch(Exception ex)
      {
         ex.printStackTrace();
      }
   }
}

This is the end of the VJ++ tutorial.


Remote Data Service Tutorials

The Remote Data Service tutorials provide step-by-step procedures that walk you through using the most common data access features.

  • RDS tutorial. This tutorial illustrates using the RDS programming model to query and update a data source.

  • Building a Simple Remote Data Service Application. This tutorial walks you through building a simple Remote Data Service application that provides access to live data in a Microsoft® Access database.

  • Address Book. This tutorial shows you how to create a simple Remote Data Service application that provides access and updatability to a Microsoft® SQL Server™ database.


RDS Tutorial

This tutorial illustrates using the RDS programming model to query and update a data source. First, it describes the steps necessary to accomplish this task. Then the tutorial is repeated in Microsoft® Visual Basic®, Scripting Edition and Microsoft® Visual J++™, featuring ADO for Windows Foundation Classes (ADO/WFC).

This tutorial is coded in different languages for two reasons:

  • The documentation for RDS assumes the reader codes in Visual Basic. This makes the documentation convenient for Visual Basic programmers, but less useful for programmers who use other languages.

  • If you are uncertain about a particular RDS feature and you know a little of another language, you may be able to resolve your question by looking for the same feature expressed in another language.

How the Tutorial is Presented

This tutorial is based on the RDS programming model. It discusses each step of the programming model individually. In addition, it illustrates each step with a fragment of Visual Basic code.

The code example is repeated in other languages with minimal discussion. Each step in a given programming language tutorial is marked with the corresponding step in the programming model and descriptive tutorial. Use the number of the step to refer to the discussion in the descriptive tutorial.

The RDS programming model is stated below. Use it as a roadmap as you proceed through the tutorial.

RDS Programming Model with Objects

  • Specify the program to be invoked on the server, and obtain a way (proxy) to refer to it from the client.

  • Invoke the server program. Pass parameters to the server program that identify the data source and the command to issue.

  • The server program obtains a Recordset object from the data source, typically by using ADO. Optionally, the Recordset object is processed on the server.

  • The server program returns the final Recordset object to the client application.

  • On the client, the Recordset object is optionally put into a form that can be easily used by visual controls.

  • Changes to the Recordset object are sent back to the server and used to update the data source.

Next Step 1


Step 1: Specify a Server Program (RDS Tutorial)

You are Here...

  • Specify the program to be invoked on the server, and obtain a proxy.

  • Invoke the server program. Pass parameters to the server program that identify the data source and the command to issue.

  • The server program obtains a Recordset object from the data source, typically by using ADO.

  • The server program returns the final Recordset object to the client application.

  • On the client, the Recordset object is optionally put into a form that can be easily used by visual controls.

  • Changes to the Recordset object are sent back to the server and used to update the data source.

Discussion

In the most general case, use the RDS.DataSpace object CreateObject method to specify the default server program, RDSServer.DataFactory, or your own custom server program (business object). A server program is instantiated on the server, and a reference to the server program, or proxy, is returned.

This tutorial uses the default server program:

Sub RDSTutorial1()
Dim DS as New RDS.DataSpace
Dim DF as Object
Set DF = DS.CreateObject("RDSServer.DataFactory", "http://yourServer")
...

Next Step 2


Step 2: Invoke the Server Program (RDS Tutorial)

You are Here...

  • Specify the program to be invoked on the server, and obtain a proxy.

  • Invoke the server program. Pass parameters to the server program that identify the data source and the command to issue.

  • The server program obtains a Recordset object from the data source, typically by using ADO.

  • The server program returns the final Recordset object to the client application.

  • On the client, the Recordset object is optionally put into a form that can be easily used by visual controls.

  • Changes to the Recordset object are sent back to the server and used to update the data source.

Discussion

When you invoke a method on the client proxy, the actual program on the server executes the method. In this step, you'll execute a query on the server.

Part A If you weren't using RDSServer.DataFactory in this tutorial, the most convenient way to perform this step would be to use the RDS.DataControl object. The RDS.DataControl combines the previous step of creating a proxy, and this step, issuing the query.

Set the RDS.DataControl object Server property to identify where the server program should be instantiated; the Connect property to specify the connect string to access the data source; and the SQL property to specify the query command text. Then issue the Refresh method to cause the server program to connect to the data source, retrieve rows specified by the query, and return a Recordset object to the client.

This tutorial doesn't use the RDS.DataControl, but this is how it would look if it did:

Sub RDSTutorial2A()
Dim DC as New RDS.DataControl
DC.Server = "http://yourServer"
DC.Connect = "DSN=pubs"
DC.SQL = "SELECT * FROM authors"
DC.Refresh
...

Nor does the tutorial invoke RDS with ADO objects, but this is how it would look if it did:

Dim rs as New ADODB.Recordset
rs.Open "SELECT * FROM authors", "Provider=MS Remote;Data Source=pubs;Remote Server=http://YourServer"

Part B The general way of performing this step is to invoke the RDSServer.DataFactory object Query method. That method takes a connect string, which is used to connect to a data source, and command text, which is used to specify the rows to be returned from the data source.

This tutorial uses the RDSServer.DataFactory Query method:

Sub RDSTutorial2B()
Dim DS as New RDS.DataSpace
Dim DF
Dim RS as ADODB.Recordset
Set DF = DS.CreateObject("RDSServer.DataFactory", "http://yourServer")
Set RS = DF.Query ("DSN=pubs", "SELECT * FROM authors")
...

Next Step 3


Step 3: Server Obtains a Recordset (RDS Tutorial)

You are Here...

  • Specify the program to be invoked on the server, and obtain a proxy.

  • Invoke the server program. Pass parameters to the server program that identify the data source and the command to issue.

  • The server program obtains a Recordset object from the data source, typically by using ADO.

  • The server program returns the final Recordset object to the client application.

  • On the client, the Recordset object is optionally put into a form that can be easily used by visual controls.

  • Changes to the Recordset object are sent back to the server and used to update the data source.

Discussion

The server program uses the connect string and command text to query the data source for the desired rows. ADO is typically used to retrieve this Recordset, although other Microsoft data access interfaces, such as OLE DB, could be used. See the ADO Tutorial for a detailed explanation of how the query is performed.

A custom server program might look like this:

Public Function ServerProgram(conn as String, qry as String) as Object
Dim rs as New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.Open cn, qry, adOpenUnspecified, adLockUnspecified, _
  adCmdUnspecified
Set ServerProgram = rs
End Function

Next Step 4


Step 4: Server Returns the Recordset (RDS Tutorial)

You are Here...

  • Specify the program to be invoked on the server, and obtain a proxy.

  • Invoke the server program. Pass parameters to the server program that identify the data source and the command to issue.

  • The server program obtains a Recordset object from the data source, typically by using ADO.

  • The server program returns the final Recordset object to the client application.

  • On the client, the Recordset object is optionally put into a form that can be easily used by visual controls.

  • Changes to the Recordset object are sent back to the server and used to update the data source.

Discussion

RDS converts the retrieved Recordset object to a form that can be sent back to the client (that is, it marshals the Recordset). The exact form of the conversion and how it is sent depends on whether the server is on the Internet or an intranet, a local area network, or is a dynamic-link library. However, this detail isn't critical; all that matters is that RDS sends the Recordset back to the client.

On the client side, a Recordset object is returned and assigned to a local variable.

Sub RDSTutorial4()
Dim DS as New RDS.DataSpace
Dim RS as New ADODB.Recordset   'Optionally, ADOR.Recordset
Dim DF as Object
Set DF = DS.CreateObject("RDSServer.DataFactory", "http://yourServer")
Set RS = DF.Query("DSN=pubs", "SELECT * FROM authors")
...

Next Step 5


Step 5: DataControl is made usable (RDS Tutorial)

You are Here...

  • Specify the program to be invoked on the server, and obtain a proxy.

  • Invoke the server program. Pass parameters to the server program that identify the data source and the command to issue.

  • The server program obtains a Recordset object from the data source, typically by using ADO.

  • The server program returns the final Recordset object to the client application.

  • On the client, the Recordset object is optionally put into a form that can be easily used by visual controls.

  • Changes to the Recordset object are sent back to the server and used to update the data source.

Discussion

The returned Recordset object is available for use. You can examine, navigate, or edit it as you would any other recordset. What you can do with the recordset depends on your environment. Microsoft Visual Basic and Visual C++ have visual controls that can use a Recordset directly, or indirectly with the aid of an enabling data control.

For example, if you are displaying a Web page in Microsoft® Internet Explorer, you might want to display the Recordset object data in a visual control. Visual controls on a Web page cannot access a Recordset object directly. However, they can access (that is, bind to) the Recordset object through an RDS.DataControl. The RDS.DataControl becomes usable by a visual control when its SourceRecordset property is set to the Recordset object.

(The visual control object must have its DATASRC parameter set to the RDS.DataControl, and its DATAFLD property set to a Recordset object field (column).)

In this tutorial, set the SourceRecordset property.

Sub RDSTutorial5()
Dim DS as New RDS.DataSpace
Dim RS as New ADODB.Recordset   'Optionally, ADOR.Recordset
Dim DC as New RDS.DataControl
Dim DF as Object
Set DF = DS.CreateObject("RDSServer.DataFactory", "http://yourServer")
Set RS = DF.Query ("DSN=pubs", "SELECT * FROM authors")
DC.SourceRecordset = RS         'Visual controls can now bind to DC.
...

Next Step 6


Step 6: Changes are Sent to the Server (RDS Tutorial)

You are Here...

  • Specify the program to be invoked on the server, and obtain a proxy.

  • Invoke the server program. Pass parameters to the server program that identify the data source and the command to issue.

  • The server program obtains a Recordset object from the data source, typically by using ADO.

  • The server program returns the final Recordset object to the client application.

  • On the client, the Recordset object is optionally put into a form that can be easily used by visual controls.

  • Changes to the Recordset object are sent back to the server and used to update the data source.

Discussion

If the Recordset object is edited, any changes (that is, rows that are added, changed, or deleted) can be sent back to the server.

Note The default behavior of RDS can be invoked implicitly with ADO objects and the MS Remote provider. Queries can return recordsets, and edited recordsets can update the data source. This tutorial doesn't invoke RDS with ADO objects, but this is how it would look if it did:

Dim rs as New ADODB.Recordset
rs.Open "SELECT * FROM authors", "Provider=MS Remote;Data Source=pubs;Remote Server=http://YourServer"
...            'Edit the recordset
rs.UpdateBatch    'The equivalent of SubmitChanges
...

Part A Assume for this case that you have only used the RDS.DataControl and that a Recordset object is now associated with the RDS.DataControl. The SubmitChanges method updates the data source with any changes to the Recordset object if the Server and Connect properties are still set.

Sub RDSTutorial6A()
Dim DC as New RDS.DataControl
Dim RS as New ADODB.Recordset   'Optionally, ADOR.Recordset
DC.Server = "http://yourServer"
DC.Connect = "DSN=pubs"
DC.SQL = "SELECT * FROM authors"
DC.Refresh
...
Set RS = DC.Recordset
...                           'Edit the Recordset
...
DC.SubmitChanges
...

Part B Alternatively, you could update the server with the RDSServer.DataFactory object, specifying a connection and a Recordset object.

Sub RDSTutorial6B()
Dim DS as New RDS.DataSpace
Dim RS as New ADODB.Recordset   'Optionally, ADOR.Recordset
Dim DC as New RDS.DataControl
Dim DF as Object
Set DF = DS.CreateObject("RDSServer.DataFactory", "http://yourServer")
Set RS = DF.Query ("DSN=pubs", "SELECT * FROM authors")
DC.SourceRecordset = RS         'Visual controls can now bind to DC.
...                           'Edit the Recordset
blnStatus = DF.SubmitChanges "DSN=pubs", RS

This is the end of the tutorial.


RDS Tutorial (VBScript)

This is a restatement of the RDS Tutorial, written in Microsoft Visual Basic, Scripting Edition.

In this tutorial, RDS.DataControl and RDS.DataSpace are created at design time— that is, they are defined with object tags, like this: <OBJECT>...</OBJECT>. Alternatively, they could be created at run time with the Server.CreateObject method. For example, the RDS.DataControl object could be created like this:

Set DC = Server.CreateObject("RDS.DataControl")

<!-- RDS.DataControl -->
<OBJECT
ID="DC1" CLASSID="CLSID:BD96C556-65A3-11D0-983A-00C04FC29E33">
</OBJECT>

<!-- RDS.DataSpace -->
<OBJECT
ID="DS1" WIDTH=1 HEIGHT=1
CLASSID="CLSID:BD96C556-65A3-11D0-983A-00C04FC29E36">
</OBJECT>

<SCRIPT LANGUAGE="VBScript">

Sub RDSTutorial()
Dim DF1 as Object

Step 1—Specify a server program

VBScript can discover the name of the IIS Web server it is running on by accessing the VBScript Request.ServerVariables method available to Active Server Pages:

"http://<%=Request.ServerVariables("SERVER_NAME")%>"

However, for this tutorial, use the imaginary server, "yourServer".

Note Pay attention to the data type of ByRef arguments. VBScript does not let you specify the variable type, so you must always pass a Variant. When using HTTP, RDS will allow you to pass a Variant to a method that expects a non-Variant if you invoke it with the RDS.DataSpace object CreateObject method. When using DCOM or an in-process server, match the parameter types on the client and server sides or you will receive a "Type Mismatch" error.

Set DF1 = DS1.CreateObject("RDSServer.DataFactory", "http://yourServer")

Step 2a—Invoke the server program with RDS.DataControl

This example is merely a comment demonstrating that the default behavior of the RDS.DataControl is to perform the specified query.

<OBJECT CLASSID="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33" ID="DC1">
<PARAM NAME="SQL" VALUE="SELECT * FROM authors">
<PARAM NAME="Connect" VALUE="DSN=Pubs;">
<PARAM NAME="Server" VALUE="http://YourServer/">
</OBJECT>
...
<SCRIPT LANGUAGE="VBScript">

Sub RDSTutorial2A()
Dim RS as New ADODB.Recordset
DC1.Refresh
Set RS = DC1.Recordset
...

Step 2b—Invoke the server program with RDSServer.DataFactory

Step 3—Server obtains a Recordset

Step 4—Server returns the Recordset

Set RS = DF1.Query("DSN=pubs", "SELECT * FROM authors")

Step 5—DataControl is made usable by visual controls

' Assign the returned recordset to the DataControl.

DC1.SourceRecordset = RS

Step 6a—Changes are sent to the server with RDS.DataControl

This example is merely a comment demonstrating how the RDS.DataControl performs updates.

<OBJECT CLASSID="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33" ID="DC1">
<PARAM NAME="SQL" VALUE="SELECT * FROM authors">
<PARAM NAME="Connect" VALUE="DSN=Pubs;">
<PARAM NAME="Server" VALUE="http://YourServer/">
</OBJECT>
...
<SCRIPT LANGUAGE="VBScript">

Sub RDSTutorial6A()
Dim RS as New ADODB.Recordset
DC1.Refresh
...
Set RS = DC1.Recordset
' Edit the Recordset object...
' The SERVER and CONNECT properties are already set from Step 2A.
Set DC1.SourceRecordset = RS
...
DC1.SubmitChanges

Step 6b—Changes are sent to the server with RDSServer.DataFactory

DF.SubmitChanges "DSN=pubs", RS

End Sub
</SCRIPT>
</BODY>
</HTML>

This is the end of the tutorial.


RDS Tutorial (VJ++)

ADO/WFC doesn't completely follow the RDS object model in that it does not implement the DataControl object. ADO/WFC only implements the client-side class, DataSpace.

The DataSpace class implements one method, createObject, which returns an ObjectProxy object. The DataSpace class also implements the InternetTimeout property.

The ObjectProxy class implements one method, call, which can invoke any server-side business object.

This is the beginning of the tutorial.

import com.ms.wfc.data.*;
public class RDSTutorial
{
public void tutorial()
{

// Step 1—Specify a server program

ObjectProxy obj =
DataSpace.createObject(
"RDSServer.DataFactory",
"http://YourServer");

// Step 2—Server returns a Recordset

Recordset rs = (Recordset) obj.call(
"Query",
new Object[] {"DSN=pubs", "SELECT * FROM authors"});

// Step 3—Changes are sent to the server

...                                // Edit Recordset
obj.call(
"SubmitChanges",
new Object[] {"DSN=pubs", rs});
return;
}
}

This is the end of the tutorial.


Building a Simple Remote Data Service Application

You can use the RDS.DataControl object to create a simple Active Server Pages file that accesses a live database.

This tutorial takes the "minimal code" approach, though the Developer's Guide provides more information for using the RDS.DataControl. In this tutorial, you will connect to a Microsoft® Access database, display a result set in a data-bound grid, and add the ability to navigate through the displayed Recordset. The following procedure outlines the steps you'll take to create this simple application:

  1. Identify the database.

  2. Insert the grid and the RDS.DataControl object.

  3. Add HTML controls.

  4. Add code to send a query to the database.

  5. Add code to submit changes to the database.

  6. Add code to move through the displayed Recordset.

  7. See the code in action.

If you want to see a finished version of this sample application, you can go to http://<webservername>/MSADC/Samples/ADCTest.asp, where <webservername> is the name of your Web server.


Identify the Database (RDS)

Before you create your .asp file, you must identify the database in the ODBC applet in Control Panel. In this example, you will use a Microsoft® Access database that is provided with Remote Data Service.

  1. At the computer running your Web server, open Control Panel.

  2. Double-click the ODBC icon, and then click System DSN.

    There are two types of data sources: User, which is available only to you, and System, which is available to anyone using the computer. Data sources for use with the Web server need to be System data sources.

  3. Click Add, choose Microsoft Access Driver, and then click Finish.

  4. In the Data Source Name box, type AdvWorks and click Select. Select the C:\Program Files\Common Files\System\MSADC\Samples\AdvWorks.mdb file, and click OK.

  5. Click OK to close the dialog boxes.

Next


Insert the Grid and the RDS.DataControl Object (RDS)

  1. Use your text editor to open the Tutorial.asp file in the C:\Program Files\Common Files\System\MSADC\Samples\Tutorial folder.

  2. Search for the words "Tutorial: RDS.DataControl Object." Copy the following script and paste it under this comment.
    <OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
  ID=ADC HEIGHT=1 WIDTH = 1>
</OBJECT>
  3. Search for the words "Tutorial: Data Bound Grid Control." Copy the following script and paste it under this comment.
    <BR>
<Center>
<OBJECT ID="GRID" WIDTH=600 HEIGHT=200 Datasrc="#ADC"
 CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/ssdatb32.cab"
 CLASSID="CLSID:AC05DC80-7DF1-11d0-839E-00A024A94B3A">
<PARAM NAME="_Version"      VALUE="131072">
<PARAM NAME="BackColor"   VALUE="-2147483643">
<PARAM NAME="BackColorOdd"  VALUE="-2147483643">
<PARAM NAME="ForeColorEven" VALUE="0">
<PARAM NAME="AllowAddNew" VALUE="TRUE">
<PARAM NAME="AllowDelete" VALUE="TRUE">
<PARAM NAME="AllowUpdate" VALUE="TRUE">
</OBJECT>
<BR>

    The DATASRC parameter in the grid control's OBJECT tag indicates that the data source will be the RDS.DataControl object ADC. This binds the grid to the returned Recordset and causes the grid to display data when the RDS.DataControl gets a Recordset. The AllowAddNew, AllowDelete, and AllowUpdate parameters enable the grid to take record additions, changes, and deletions from the user.

Next


Add HTML Controls (RDS)

  1. Search for the words "Tutorial: HTML Controls to Get Recordsets." Copy the following script and paste it under this comment.
    <BR>
<table>
<tr><td>RDS Server:<td><INPUT NAME=Server SIZE=70>
<tr><td>Connection:<td><INPUT NAME=Connect SIZE=70>
<tr><td>Query:<td><INPUT NAME=SQL SIZE=70>
</table>

    This adds some text boxes for users to specify an SQL query to send to a database (specified in the data source name) that will return a disconnected Recordset to the client.

  2. Search for the words "Tutorial: HTML Controls to Navigate the Recordset and Run the Query." Copy the following script and paste it under this comment.
    <BR>
<BR>
<INPUT TYPE=BUTTON NAME="Run" VALUE="Run!" >
<INPUT TYPE=BUTTON NAME="First" VALUE="First" >
<INPUT TYPE=BUTTON NAME="Next" VALUE="Next" >
<INPUT TYPE=BUTTON NAME="Prev" VALUE="Previous" >
<INPUT TYPE=BUTTON NAME="Last" VALUE="Last" >
<INPUT TYPE=BUTTON NAME="Submit" VALUE="Submit Changes" >
</CENTER>

    The First, Next, Previous, and Last buttons will eventually provide a mechanism for users to navigate through the displayed Recordset.

Next


Add Code to Send a Query to the Database (RDS)

Search for the words "Tutorial: Send a Query to the Database." Copy the following script and paste it under the comment.

SUB Run_OnClick
   ADC.Server = Server.Value
   ADC.Connect = Connect.Value
   ADC.SQL = SQL.Value

   ADC.Refresh
END SUB

Note When you specify the data source through the Connect property, you will usually provide a data source name, user ID, and password (for example, "DSN=SalesDB;UID=Manager;PWD=secret;"). With Microsoft Access databases, you don't need to specify a user ID (UID) or password (PWD).

Next


Add Code to Submit Changes to the Database (RDS)

Add Code to Submit Changes to the Database

Search for the words "Tutorial: Submit Changes to the Database." Copy the following script and paste it under the comment.

SUB Submit_OnClick  ' Submit Changes button clicked.
  ADC.SubmitChanges ' Send changes to the DBMS.
  ADC.Refresh      ' Refresh the recordset.
End Sub

When ADC.SubmitChanges executes, Remote Data Service packages all the update information and sends it to the server via HTTP. The update is all-or-nothing; if a part of the update isn't successful, none of the changes is made, and a status message is returned.

Next


Add Code to Move through the Displayed Recordset (RDS)

You can use the Move methods with the Recordset in the RDS.DataControl object to navigate through the data records displayed in the data-bound controls on a Web page. For example, suppose you display a Recordset in a grid by binding to an RDS.DataControl object. You can then include First, Last, Next, and Previous buttons that users can click to move to the first, last, next, or previous record in the displayed Recordset. You do this by calling the MoveFirst, MoveLast, MoveNext, and MovePrevious methods of the RDS.DataControl object in the OnClick procedures for the First, Last, Next, and Previous buttons, respectively.

Search for the words "Tutorial: Move Through the Displayed Recordset." Copy the following script and paste it under the comment.

SUB First_OnClick
   ADC.Recordset.MoveFirst
END SUB

SUB Next_OnClick
   If ADC.Recordset.EOF Then   'cannot move beyond bottom record
      ADC.Recordset.MoveFirst
      Exit Sub
   End If

   ADC.Recordset.MoveNext
END SUB

SUB Prev_OnClick
   If ADC.Recordset.BOF Then   'cannot move beyond top record
      ADC.Recorset.MoveFirst   'Get out of BOF buffer
      ADC.Recordset.MoveLast
      Exit Sub
   End If
   ADC.Recordset.MovePrevious
END SUB

SUB Last_OnClick
   ADC.Recordset.MoveLast
END SUB

Next


See the Code in Action (RDS)

  1. Save the changes to the Tutorial.asp file as a text file and exit your text editor. Be sure your text editor doesn't replace the .asp file name extension. An .asp file is an Active Server Pages script file.

  2. To verify that the ASP page you've created works, point your browser to http://<webservername>/MSADC/Samples/Tutorial/Tutorial.asp, where <webservername> is the actual name of your Web server.

Note You must access your ASP page by pointing to the address. It won't open correctly if you use the Open command on the File menu, or double-click the .asp file.

When you load the page, click Run! to fill the grid with data. You can change the query or other parameters and click Run! again to see other data.


Tutorial: Address Book

This sample application shows you how to use Remote Data Service to build a simple, data-aware Web application—an online corporate address book. This tutorial is useful for Microsoft® Visual Basic®, Scripting Edition (VBScript) and ActiveX® programmers who want to learn how to use data-aware ActiveX controls with Remote Data Service, and for more experienced application developers who want to build data-centric Web applications.

This tutorial assumes you know how to use basic HTML layout tags and program with ActiveX controls.

The Address Book tutorial lessons will guide you through:

  • Making sure you meet the system requirements to run this application.

  • Setting up the environment to connect to a database, and running an SQL query to copy the sample data.

  • Setting up the HTML framework on the Web page, and writing VBScript code to handle user events.

Introduction to Address Book

The Address Book sample application is an online address book that you can use to publish a directory over an intranet. The address book is designed so that a user can enter a search string in one or more fields to request information about employees. To show you the basic features of Remote Data Service, the sample application is intentionally kept small, with a minimum number of objects and search fields.

The application front end consists of the following parts:

  • Text boxes that act as search fields for different kinds of information about an employee.

  • Command buttons to build queries, clear search fields, update the database with employee information, or cancel pending changes.

  • A spreadsheet-like grid that displays the search results and is bound to a back-end database through a nonvisual RDS.DataControl data-binding object.

  • Buttons that let you navigate the rows of data displayed in the grid.


Running the Address Book Sample Application

To get the Address Book application up and running quickly, follow this procedure.

To run this application

  1. Make sure you meet the system requirements.

  2. Set up the ODBC System DSN.

  3. Run the SQL script to load the data into your Microsoft SQL Server database.

  4. Make sure that Microsoft® SQL Server™ is running. Click Start, point to Programs, point to Microsoft SQL Server 6.5, and then click SQL Service Manager. If the stoplight is green, then SQL Server is running. If it isn't, click Start/Continue.

  5. In Microsoft® Internet Explorer 4.0 or later, type the following address:

    http://webserver/msadc/samples/AddressBook/AddrBook.asp

    where webserver is the name of the Web server where the Remote Data Service server components are installed, and where you created the System DSN.

  6. You can then try various scenarios in the Address Book sample application, such as looking for a person based on his or her e-mail name, listing all people with the title "Program Manager," or editing and updating existing records. Click Find to fill the data grid with all the available names.


System Requirements for the Address Book Application

To set up the Address Book sample application, you need to meet the following software and database requirements.

Software Requirements

The server computer software requirements for running this Web application include:

  • Microsoft® Windows NT® Server x86, version 4.0 Service Pack 3 or later.

  • Microsoft® Internet Information Server (IIS) 3.0 or later, with Active Server Pages.

  • Server-side DLLs for Remote Data Service. (Remote Data Service setup does this for you automatically.)

The client computer software requirements for running this Web application include:

  • Microsoft® Internet Explorer 4.0 or later.

  • Microsoft® Windows NT® Workstation or Microsoft® Windows® 95.

  • Client-side DLLs for Remote Data Service installed on the client computer. They are already included as part of the Internet Explorer 4.0 installation.

Database Requirements

To use this sample, you must have:

  • An operational Microsoft SQL Server version 6.5 database.

  • Access permissions to the database.

  • Write privileges to populate the database with the sample data.

  • Verification of the populated data through Enterprise Manager or ISQL utilities.

If you don't have privileges, your database administrator may need to set up the system and give you access permission to the database, or set up the database for you.

Once you meet these database requirements, follow the instructions in "Running the Address Book SQL Script" and "Setting Up an ODBC Connection for Address Book."


Setting Up an ODBC Connection for Address Book

You need to set up an ODBC System data source name (DSN) on the Web server where the Remote Data Service server components will be installed.

This setup assumes that the Employee table was created in the AddrBookDB database on a local SQL Server running on the Web server by running the SQL script. If you want to use another database or another SQL Server running on a separate server, then you must change the values for Server and Database Name in the ODBC SQL Server Setup dialog box. If you do so, you will also have to make small changes in the included AddrBook page.

To set up the DSN for a Windows NT® client

  1. On the Web server, click Start, point to Settings, and then click Control Panel.

  2. In Control Panel, double-click the ODBC icon.

  3. On the System DSN tab, click Add.

  4. In the Create New Data Source box, select SQL Server and click Finish.

  5. Follow the instructions in the "Create a New Data Source to SQL Server" wizard. If you need assistance, click Help in the wizard dialog box.

  6. When you are finished, click OK to return to the ODBC Data Source Administrator dialog box. Click Close to exit ODBC setup.

To set up the DSN for a Windows 95 client

  1. On the Web server, click Start, point to Settings, and then click Control Panel.

  2. In Control Panel, double-click the ODBC icon.

  3. Click System DSN.

  4. In the System Data Sources box, click Add, select SQL Server, and click OK.

  5. Follow steps 5 and 6 in the previous Windows NT client procedure.


Running the Address Book SQL Script

You must use either the ISQL command-line utility or the SQL Server Enterprise Manager to run an SQL script that:

  • Creates a new database, AddrBookDB, on the default device.

  • Connects to the correct database (AddrBookDB; if you rename your database, make sure you change the Database Name in the ODBC connection DSN setup).

  • Creates an Employee table.

  • Populates the table with sample data.

  • Runs a simple SELECT statement to verify the population of the database table.

  • Sets up a user account called "ADCDemo" with a password of "ADCDemo."

You must run the supplied SQL script file (Sampleemp.sql) to create and populate the Employee table. By default, the Employee table is created in a newly created database, AddrBookDB, on the local SQL server.

To run the Sampleemp.sql script

  1. Click Start, point to Programs, then point to Microsoft SQL Server 6.5. Click SQL Enterprise Manager.

  2. From the Tools menu, choose SQL Query Tool.

  3. Click the Load SQL Script button (the open folder on the toolbar) and browse to Program Files\Common Files\System\MSADC\Samples\AddressBook.

  4. Choose the file Sampleemp.sql. Click Open. Click the Execute Query button (the green arrow on the toolbar).

  5. After it executes, close the Query and Enterprise Manager windows.


Address Book Sample Application Code Overview

The program code for the Address Book application is organized into the following sections. Each section highlights a group of the application's major components, shows the source code for the components, and describes how the code works.

Each section also includes the VBScript code that is executed in response to user events, such as a click. The VBScript part of the Address Book application assembles search text into queries, sends the requests to the server, identifies where to display received results from the server, and handles all button click events.

Code section | Description
HTML framework | Contains the HTML skeleton enclosing the application code.
Text boxes | Act as search fields for different kinds of information about an employee.
Command buttons | Build queries, clear search fields, update the database with employee information, or cancel pending changes.
Spreadsheet-like grid | Displays the search results and is bound to a back-end database through a nonvisual RDS.DataControl data-binding object.
RDS.DataControl data-binding object | Binds data from the Microsoft SQL Server database to the grid on the client HTML page.
Navigation buttons | Used to navigate the rows of data displayed in the grid.
VBScript initialization code | Initializes the data grid column headings and grid title.

The Address Book sample application is structured so that you will learn how to build a simple Remote Data Service Web application in incremental steps, adding functionality at each step. For ease of presentation, the tutorial omits repetitive code and does not always describe code portions according to their sequence in the program. Click here if you want to view the complete source code for the Address Book application.

Copy and paste the code from the tutorial topics into your project using a text editor such as Notepad. Save the project as Tutorial2.asp in your Program Files\Common Files\System\Msadc\Samples\Tutorial directory. To view it, in Internet Explorer 4.0, type http://webserver/msadc/samples/Tutorial/Tutorial2.asp

where webserver is the name given to your Windows NT® Web server running Internet Information Server and ASP.


HTML Framework for Address Book

The first step in building a Remote Data Service application is to set up the standard HTML Web page framework. The HTML skeleton contains the program code for the application objects you use, such as buttons, text boxes, and data-aware controls.

The following code fragment shows the HTML skeleton for the Address Book application. This part includes the standard HTML heading and page structure tags, comments identifying the application, and Web page text, font, and color information.

Comments are added at locations where the application objects (such as buttons, text boxes, and data-aware controls) are located. These are places where you can drop in your own application components. Click those placeholder comments to take you to descriptions of those parts of the application.

Note Most of the common HTML tags, and those that define the Web page background attributes, will not be defined here. The SCRIPT tag indicates that control is passed to a scripting language—in this case, VBScript.

<HTML>
<HEAD>
<TITLE>Corporate Address Book</TITLE>
</HEAD>

<!--
   Purpose:   To provide a company directory search service for Web users.
   Written By:   Microsoft Remote Data Service Team, Microsoft Corp.
   Date:      April, 1997
-->

<BODY BACKGROUND="Arcadia.gif" LANGUAGE="VBScript" onload="Load">
<tr>
   <td align="center" width="40%">
    <table border="2" cellpadding="7" cellspacing="7">
    <tr>
      <td width="100%"><font color="#160B5A"><font
      size="4"><strong>Arcadia Bay Corporate Phone Directory</strong></font></font></td>
    </tr>
    </table>
    </td>
</tr>

<hr>
<h2><font color = "#160B5A">Search Parameters</h2>
<h5><font color = "#160B5A">Please enter one or more search patterns and press FIND to search.</h5>

<PRE>First Name
<!-- HTML CODE FOR TEXT BOXES GOES HERE -->

<!-- HTML CODE FOR COMMAND BUTTONS GOES HERE-->
<hr>
<h2><font color = "#400040">Search Results</h2>
</B>
<br>
<!-- HTML CODE FOR DATA GRID GOES HERE -->
<!-- HTML CODE FOR NAVIGATION BUTTONS GOES HERE -->

<!-- CODE FOR RDS.DATACONTROL OBJECT GOES HERE -->

<SCRIPT Language="VBScript">

<!-- VBSCRIPT CODE FOR INITIALIZING CLEARING TEXT BOXES, SUBMITTING A QUERY, NAVIGATING THROUGH THE DISPLAYED RECORDSET, SAVING CHANGES TO A RECORD, AND CANCELING ANY PENDING CHANGES GOES HERE. -->
</SCRIPT>

<BR>
<font color = "#400040">This site powered by Microsoft Remote Data Service. </font>
</BODY>
</HTML>


Address Book Text Boxes

The Address Book application contains four text boxes for entering search phrases (for example, the First Name box). The following HTML code defines the text box objects:

<PRE> First Name   <INPUT NAME=SFirst SIZE=30> </PRE>

<PRE> Last Name  <INPUT NAME=SLast  SIZE=30> </PRE>

<PRE> Title    <INPUT NAME=STitle SIZE=30> </PRE>

<PRE> E-mail Alias <INPUT NAME=SEmail SIZE=30> </PRE>

The intrinsic INPUT control is built into HTML. The NAME parameter defines what it will be called in code. For example, the VBScript code can check SFirst.Value for text in the First Name box. The SIZE parameter lets you adjust the length of the text box, in characters.


Address Book Command Buttons

The Address Book application includes the following command buttons:

  • A Find button to submit a query to the database.

  • A Clear button to clear the text boxes before starting a new search.

  • An Update Profile button to save changes to an employee record.

  • A Cancel Changes button to discard changes.

Find Button

The following HTML statement defines the Find button. This HTML statement appears before the VBScript section of the program. Copy and paste this control just following the comment for HTML command buttons.

<INPUT TYPE=BUTTON NAME="Find"    VALUE="Find">

Find_OnClick Sub Procedure

Clicking the Find button activates the VBScript Find_OnClick Sub procedure, which builds and sends the SQL query. When you complete the project, click this button to fill the data grid.

Building the SQL Query

The first part of the Find_OnClick Sub procedure builds the SQL query, one phrase at a time, by appending text strings to a global SQL SELECT statement. It begins by setting the variable myQuery to an SQL SELECT statement that requests all rows of data from the data source table. Copy and paste this code beneath the opening SCRIPT tag.

Sub Find_OnClick

myQuery = "Select FirstName, LastName, Title, Type, Email, " _
   & "ManagerEmail, Building, Room, Phone from Employee"

Next, the Sub procedure scans each of the four input boxes of the Address Book. Copy and paste this code within the Find subroutine.

   If (SFirst.Value <> "") Then
      myQuery = myQuery + " where FirstName like '" + SFirst.Value + "%'"
   End If

   IF (SLast.Value <> "") Then
      myQuery = myQuery + " where LastName like '" + SLast.Value + "%'"
   End If

   If (STitle.Value <> "") Then
      myQuery = myQuery + " where Title like '" + STitle.Value + "%'"
   End If

   If (SEmail.Value <> "") Then
      myQuery = myQuery + " where Email like '" + SEmail.Value + "%'"
   End If

Each If statement scans its corresponding text box for text. If the text box contains text, the Then statement executes, appending the quoted text to the global SELECT statement contained in the variable myQuery. Because the program uses the word like in building the SQL statements, the queries are substring searches rather than exact matches.

For example, if the Last Name box contained the entry "Berge" and the Title box contained the entry "Program Manager", the SQL statement (value of myQuery) would read:

Select FirstName, LastName, Title, Email, Building, Room, Phone from Employee where lastname like 'Berge%' and title like 'Program Manager%'

If the query was successful, all persons with a last name containing the text "Berge" (such as Berge and Berger), with a title containing the words "Program Manager" (for example, Program Manager, Advanced Technologies) are displayed in the data grid.

Preparing and Sending the Query

The last part of the Find_OnClick Sub procedure consists of two statements. The first statement assigns the SQL query property of the RDS.DataControl object equal to the dynamically built SQL query. The second statement causes the RDS.DataControl object (SControl) to query the database, and then display the new results of the query in the grid. Copy and paste this code into the Find subroutine.

   SControl.SQL = myQuery
   SControl.Refresh
End Sub

Clear Button

The following HTML statement defines the Clear button. This HTML statement appears before the VBScript section of the program. Copy and paste this code just following the Find HTML button.

<INPUT TYPE=BUTTON NAME="Clear"    VALUE="Clear">

The INPUT tag defines an element, such as a button, option button, check box, or text. You use the TYPE parameter to specify the element, which in this case, is a button. The NAME parameter defines what the button will be called in code. The VALUE parameter specifies the labels associated with the button (Clear) that will be displayed on the page.

Clear_OnClick Sub Procedure

Clicking the Clear button activates the VBScript Clear_OnClick Sub procedure. Copy and paste this code between the SCRIPT and /SCRIPT tags.

Sub Clear_OnClick
   SFirst.Value=""
   SLast.Value=""
   STitle.Value=""
   SEmail.Value=""
End Sub

When the Sub procedure is executed, it initializes each of the four HTML input boxes, which it identifies by the NAME parameter of the ID tag. The property .Value indicates characters in the text box object that are displayed on the Web page. The procedure replaces any text with a zero length string ("") in preparation for a new find.

Update Profile Button

The following code defines the Update Profile button. This HTML statement appears before the VBScript section of the program. Copy and paste this HTML control just following the Clear button.

<INPUT TYPE=BUTTON NAME="Update"    VALUE="Update Profile">

The INPUT tag defines an element, such as a button, option button, check box, or text. The NAME parameter defines what the button will be called in code. You use the TYPE parameter to specify the type of form element—in this case, a button. The VALUE parameter specifies the label associated with the button (Update Profile).

Update_OnClick Sub Procedure

Clicking the Update Profile button activates the VBScript Update_OnClick Sub procedure, which executes the RDS.DataControl object's (SControl) SubmitChanges and Refresh methods. Copy and paste this code between the SCRIPT and /SCRIPT tags.

Sub Update_OnClick
   SControl.SubmitChanges
   SControl.Refresh
End Sub

When SControl.SubmitChanges executes, the program packages all the update information and sends it to the server via HTTP. The update is all-or-nothing; if a part of the update isn't successful, none of the changes is made, and a status message is returned. SControl.Refresh isn't necessary after SubmitChanges with Remote Data Service 1.5, but it ensures fresh data.

Cancel Changes Button

The following code defines the Cancel Changes button. This HTML statement appears before the VBScript section of the program. Copy and paste this HTML control just following the Update button.

<INPUT TYPE=BUTTON NAME="Cancel"    VALUE="Cancel Changes">

Cancel_OnClick Sub Procedure

Clicking Cancel Changes activates the VBScript Cancel_OnClick Sub procedure, which executes the RDS.DataControl object's (SControl) CancelUpdate method. Copy and paste this code between the SCRIPT and /SCRIPT tags.

Sub Cancel_OnClick
     SControl.CancelUpdate
End Sub

When SControl.CancelUpdate executes, it discards any edits that a user has made to an employee record on the data grid since the last query or update. It restores the original values.


Address Book Data-Binding Object

The Address Book application uses the RDS.DataControl object to bind data from the SQL Server database to a visual object (in this case, a grid display) in the application's client HTML page. The event-driven VBScript program logic uses the RDS.DataControl to:

  • Query the database, send updates to the database, and refresh the data grid.

  • Let users move to the first, next, previous, or last record in the data grid.

The following code defines the RDS.DataControl component:

<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=SControl Width=1 Height=1>
   <PARAM NAME="SERVER" VALUE="http://<%=Request.ServerVariables("SERVER_NAME")%>">
   <PARAM NAME="CONNECT" VALUE="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;">
</OBJECT>

The OBJECT tag defines the RDS.DataControl component in the program. The tag includes two types of parameters:

  • Those associated with the generic OBJECT tag.

  • Those specific to the RDS.DataControl object.

Generic OBJECT Tag Parameters

The following table describes the parameters associated with the OBJECT tag.

Parameter | Description
CLASSID | A unique, 128-bit number that identifies the type of embedded object to the system. This identifier is maintained in the local computer's system registry. (For the class IDs of the RDS.DataControl object, see RDS.DataControl Object.)
ID | Defines a document-wide identifier for the embedded object that is used to identify it in code.

RDS.DataControl Tag Parameters

The following table describes the parameters specific to the RDS.DataControl object. (For a complete list of the RDS.DataControl object parameters, and when to implement them, see RDS.DataControl object.)

Parameter | Description
SERVER | If you are using HTTP, the value is the name of the server computer preceded by HTTP://.
CONNECT | The first part of this VALUE indicates the System DSN that points to the data source; the second and third parts specify the user ID and password needed to access the data source (for example, "DSN=ADCDEMO;UID=adcdemo;PWD=adcdemo;"). If you need assistance, your system database administrator can probably provide the information for you.
SQL | Sets or returns the query string used to retrieve the Recordset.


Address Book Data Grid

The grid control is a spreadsheet-like object. The Address Book application uses it to display data returned from queries.

The following HTML code defines the grid control. Copy and paste this code just following the comment tag that refers to it.

<OBJECT CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/ssdatb32.cab"
   ID=GRID1
DATASRC=#SControl
HEIGHT=125
WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="BackColor"   VALUE="-2147483643">
   <PARAM NAME="BackColorOdd"  VALUE="-2147483643">
   <PARAM NAME="ForeColorEven" VALUE="0">
</OBJECT>
<HR>

The OBJECT tag defines the grid control component to the program. The tag includes parameters that allow you to set the size of the grid, change the data displayed when information is updated or deleted, and dynamically change the number of rows according to the results of a query. The other parameters set the color properties of the grid control.

The following table describes the parameters associated with the OBJECT tag.

Parameter | Description
CLASSID | A unique, 128-bit number that identifies the type of embedded object to the system. This identifier is maintained in the local computer's Windows registry. It is specific to this Sheridan grid control.
CODEBASE | Specifies the location of a source file of the object being called, if it is not on the client computer. In this case, CODEBASE specifies the location of a .cab file containing the Sheridan ActiveX® controls. The program uses Active Server Pages script (the code enclosed by the <% and %> signs) to request the server name part of the URL.
ID | Defines a document-wide identifier for the embedded object.
DATASRC | Identifies the data source that is used to bind the data grid to back-end data (in this case, SControl, which is an RDS.DataControl object).
WIDTH and HEIGHT | Identifies the dimensions of the control in pixels.

For the Address Book application, the grid object uses several additional parameters to enable editing. Without these specifiers, the grid can only present a read-only, static view of the editable data. The following table lists editing parameter settings for the grid control in this sample application.

Parameter | Value | Description
AllowAddNew | TRUE | Allows an existing data display to add new records.
AllowDelete | TRUE | Allows an existing data display to remove records.
AllowUpdate | TRUE | Allows changes to a cell in the grid.

The BackColor, BackColorEven, and BackColorOdd parameters set the grid to a white background with black text.


Address Book Navigation Buttons

The Address Book application displays the navigation buttons at the bottom of the Web page. You can use the navigation buttons to navigate around the data in the grid display by selecting either the first or last row of data, or rows adjacent to the current selection.

The following code defines the navigation buttons. These HTML statements appear before the VBScript section of the program. Copy and paste these controls following the comment tag that refers to them.

<INPUT TYPE=BUTTON NAME="First"       VALUE="First">
<INPUT TYPE=BUTTON NAME="Prev"       VALUE="Previous">
<INPUT TYPE=BUTTON NAME="Next"      VALUE="Next">
<INPUT TYPE=BUTTON NAME="Last"      VALUE="Last">

HTML uses the INPUT tag to define a form element, such as a button, option button, check box, or text. You use the TYPE parameter to specify the type of form element, which in this case is a button. The NAME parameter defines what the button will be called in code. The VALUE parameter specifies the labels associated with the button (First, Previous, Next, and Last) that are displayed on the page.

When a user clicks a button, an event is generated, and VBScript activates the appropriate navigation Sub procedure.

Navigation Sub Procedures

The Address Book application contains several procedures that allow users to click the First, Next, Previous, and Last buttons to move around the data. To enable movement, you can specify the method of the RDS.DataControl object (SControl) to the type of movement you want. The method differs for each navigation button.

For example, clicking the First button activates the VBScript First_OnClick Sub procedure. The procedure executes a MoveFirst method, which makes the first row of data the current selection. Clicking the Last button activates the Last_OnClick Sub procedure, which invokes the MoveLast method, making the last row of data the current selection. The remaining navigation buttons work in a similar fashion. Copy and paste this code between the SCRIPT and /SCRIPT tags.

' Move to the first record in the bound recordset.
Sub First_OnClick
   SControl.Recordset.MoveFirst
End Sub

' Move to the next record from the current position
' in the bound recordset.
Sub Next_OnClick
   If SControl.Recordset.EOF Then   'cannot move beyond bottom record
      SControl.Recordset.MoveFirst
      SControl.Recordset.MoveNext
      Exit Sub
   End If

   SControl.Recordset.MoveNext

End Sub

' Move to the previous record from the current position in the bound
' recordset.
Sub Prev_OnClick
   If SControl.Recordset.BOF Then   'cannot move beyond top record
      SControl.Recordset.MoveLast   'Get out of BOF buffer
      SControl.Recordset.MovePrevious
      Exit Sub
   End If
   SControl.Recordset.MovePrevious

End Sub

' Move to the last record in the bound recordset.
Sub Last_OnClick
   SControl.Recordset.MoveLast
End Sub


VBScript Initialization Code

The VBScript section of the Address Book application first declares the variable myQuery. This variable will contain the SQL query that is dynamically built from text in the search fields and sent to the database. Later, the Find_OnClick Sub procedure sets the value of this variable.

Dim myQuery

The remaining initializations are contained in the Load Sub procedure. These include adding a caption to the data grid. The WHERE clause is such that no records are pulled, so that only column headings are provided. Copy and paste this code between the SCRIPT and /SCRIPT tags.

Sub Load
   Grid1.Caption = "Arcadia Bay Corporate Phone Directory"

   ' Initialize the data grid with column names only.
   SControl.SQL = "Select FirstName, LastName, Title, Email, " _
      & "Building, Room, Phone from Employee where 2 < 1"
   SControl.Refresh
End Sub


Address Book Application Source Code

The following code is the complete source code for the Address Book sample application.

<HTML>
<HEAD>
<TITLE>Corporate Address Book</TITLE>
</HEAD>

<!--
   Purpose:   To provide a company directory search service for Web users.
   Written By:   Microsoft Remote Data Service Team, Microsoft Corp.
   Date:   April, 1997
-->

<BODY BACKGROUND="Arcadia.gif" LANGUAGE="VBScript" onload="Load">
<tr>
   <td align="center" width="40%">
      <table border="2" cellpadding="7" cellspacing="7">
         <tr>
            <td width="100%"><font color="#160B5A"><font
            size="4"><strong>Arcadia Bay Corporate Phone
            Directory</strong></font></font></td>
         </tr>
      </table>
      </td>
</tr>

<hr>
<h2><font color = "#160B5A">Search Parameters</h2>
<h5><font color = "#160B5A">Please enter one or more search patterns and press FIND to search.</h5>

<FONT COLOR = "#160B5A"><B>

<PRE> First Name   <INPUT NAME=SFirst SIZE=30> </PRE>

<PRE> Last Name  <INPUT NAME=SLast  SIZE=30> </PRE>

<PRE> Title    <INPUT NAME=STitle SIZE=30> </PRE>

<PRE> E-mail Alias <INPUT NAME=SEmail SIZE=30> </PRE>

<!--
   Command button options:
   -----------------------
   Find      Submit a search request to the database.
   Clear      Clear the QBE fields (labor saving function only).
   Update Profile   Send updated "address profile" back to the database.
   Cancel Changes   Undo all changes since the last Update Profile.
-->

<INPUT TYPE=BUTTON NAME="Find"    VALUE="Find">
<INPUT TYPE=BUTTON NAME="Clear"    VALUE="Clear">
<INPUT TYPE=BUTTON NAME="Update"    VALUE="Update Profile">
<INPUT TYPE=BUTTON NAME="Cancel"    VALUE="Cancel Changes">

<hr>
<h2><font color = "#400040">Search Results</h2>
</B>
<br>

<!--
   This Sheridan DataGrid control (SGrid) is initialized to
   allow changes to the data - these changes will be saved
   to the database when the Update Profile button is pressed.
-->

<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/ssdatb32.cab"
   ID=GRID1
    datasrc=#SControl
    HEIGHT=125
    WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="BackColor"   VALUE="-2147483643">
   <PARAM NAME="BackColorOdd"  VALUE="-2147483643">
   <PARAM NAME="ForeColorEven" VALUE="0">
</OBJECT>

<br>
<br>
<INPUT TYPE=BUTTON NAME="First"    VALUE="First">
<INPUT TYPE=BUTTON NAME="Prev"    VALUE="Previous">
<INPUT TYPE=BUTTON NAME="Next"   VALUE="Next">
<INPUT TYPE=BUTTON NAME="Last"   VALUE="Last">
<hr>

<!-- Non-visual controls - RDS.DataControl -->

<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=SControl
   WIDTH=1 HEIGHT=1>
   <PARAM NAME="SERVER" VALUE="http://<%=Request.ServerVariables("SERVER_NAME")%>">
   <PARAM NAME="CONNECT" VALUE="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;">
</OBJECT>

<!-- VBS scripting for composing queries, updating profiles, and retrieving search results. -->

<SCRIPT LANGUAGE="VBScript">

Dim myQuery

Sub Load
   Grid1.CAPTION = "Arcadia Bay Corporate Phone Directory"

   'Initialize data grid with column names only.
   SControl.SQL = "Select FirstName, LastName, Title, Email, Building, Room, Phone from Employee where 2 < 1"
   SControl.Refresh

End Sub

'Implement "Clear" button - clears all of the QBE fields in preparation for a new "Find."

Sub Clear_OnClick
   SFirst.Value=""
   SLast.Value=""
   STitle.Value=""
   SEmail.Value=""
End Sub

'Implement "Find" button - composes a dynamic SQL query to be processed by the database and returns matching records to be bound to the SGrid object.

Sub Find_OnClick

   myQuery = "Select FirstName, LastName, Title, Type, Email, ManagerEmail, Building, Room, Phone from Employee"

   'Check QBE fields and compose a dynamic SQL query.

   IF (SFirst.Value <> "") THEN
      myQuery = myQuery + " where FirstName like '" + SFirst.Value + "%'"
   End IF

   IF (SLast.Value <> "") THEN
      myQuery = myQuery + " where LastName like '" + SLast.Value + "%'"
   End IF

   IF (STitle.Value <> "") THEN
      myQuery = myQuery + " where Title like '" + STitle.Value + "%'"
   End IF

   IF (SEmail.Value <> "") THEN
      myQuery = myQuery + " where Email like '" + SEmail.Value + "%'"
   End IF

   'Set the new query and then refresh the SControl so that the new results are displayed.

   SControl.SQL = myQuery
   SControl.Refresh

End Sub

'Navigation subroutines - based on currency changes to RDS.DataControl (SControl).

'Move to the first record in the bound recordset.

Sub First_OnClick
     SControl.Recordset.MoveFirst
End Sub

'Move to the next record from the current position in the bound recordset.

Sub Next_OnClick
   If SControl.Recordset.EOF Then   'cannot move beyond bottom record
      SControl.Recordset.MoveFirst
      SControl.Recordset.MoveNext
      Exit Sub
   End If

   SControl.Recordset.MoveNext

End Sub

'Move to the previous record from the current position in the bound recordset.

Sub Prev_OnClick
If SControl.Recordset.BOF Then   'cannot move beyond top record
      SControl.Recordset.MoveLast   'Get out of BOF buffer
      SControl.Recordset.MovePrevious
      Exit Sub
   End If
   SControl.Recordset.MovePrevious
End Sub

'Move to the last record in the bound recordset.

Sub Last_OnClick
     SControl.Recordset.MoveLast
End Sub

'Submit edits made and pull a clean copy of the new data.

Sub Update_OnClick
     SControl.SubmitChanges
   SControl.Refresh    ' A Refresh is not required in ADC 1.5 after a SubmitChanges, but it ensures fresh data.
End Sub

'Cancel edits and restore original values.

Sub Cancel_OnClick
     SControl.CancelUpdate
End Sub

</SCRIPT>

<BR>
<font color = "#400040">This site powered by Microsoft Remote Data Service. </font>
</BODY>
</HTML>


Sample Applications for Remote Data Service

Remote Data Service includes several sample applications that are valuable learning tools. Throughout the documentation, you'll find sample code and applications that illustrate programming techniques. You can copy any part of them into your own applications and modify them as necessary.

Remote Data Service provides the following sample applications that demonstrate how to use this technology to build intranet and Internet applications. If you have installed the applications, the samples will be available from the locations listed as follows. If you have not installed the applications, you can install them from the MSDN™ CD-ROM.

Sample application | Path | Description
ADCTest | Installed to <device>:\Program Files\Common Files\System\MSADC\Samples\tutorial\tutorial.asp. | A simple .asp file that you can use to validate your Remote Data Service installation.
Address Book | Installed to <device>:\Program Files\Common Files\System\MSADC\Samples\AddressBook\addrbook.asp. | A simple company directory application. For detailed information about this application, see the Address Book Sample Application.
Selector | Installed to <device>:\Program Files\Common Files\System\MSADC\Samples\Selector\SampStart.asp | Shows how to implement various Remote Data Service application configurations on the client, middle, and data source tiers.

These samples are provided in .asp format (your host server name is supplied automatically), but you can easily modify them to run as .htm pages.

To modify the samples to run in .htm format

  1. Open the .asp file in a text editor such as Notepad.

  2. Replace the string <%=Request.ServerVariables("SERVER_NAME")%> with the name of your Web server machine name.

Note Companies, names, and data used in examples are fictitious unless otherwise noted.


RDS Developer's Guide

Remote Data Service Developer's Guide

The Remote Data Service (RDS) is designed for building data-centric Web applications. It incorporates existing technologies, such as ActiveX®; Microsoft® Internet Information Server (IIS); Microsoft® Visual Basic®, Scripting Edition; JScript™; and OLE DB, and introduces innovations such as enhanced data binding for Web pages, client-side caching, and the ability to invoke custom business objects.

There are many related technologies that you use in an RDS application. The Developer's Guide describes the various parts of a three-tiered RDS application and provides code examples to show you how to use those technologies.

This section contains information about:

  • Understanding Remote Data Service Applications

  • Developing Remote Data Service Applications

  • Troubleshooting Remote Data Service


Understanding Remote Data Service Applications

The following sections describe the architecture and components of Remote Data Service technology. It shows how the RDS client- and server-side components work together to:

  • Bring data over the Internet or your intranet to your Web page.

  • Allow updated information to be sent back across the network and merged into your database.

This section contains information about:

  • Three-Tiered Applications

  • How a Remote Data Service Application Works

  • Related Technologies


Three-Tiered Applications

To use Remote Data Service technology, you must understand the three-tiered client/server model. This model separates the various components of a client/server system into three "tiers":

  • Client tier—a local computer on which either a Web browser displays a Web page that can display and manipulate data from a remote data source, or (in non–Web-based applications) a stand-alone compiled front-end application.

  • Middle tier—a Microsoft® Windows NT® Server computer that hosts components that encapsulate an organization's business rules. Middle-tier components can be either Active Server Page scripts executed on Internet Information Server, or (in non–Web-based applications) compiled executables.

  • Data source tier—a computer hosting a database management system (DBMS), such as a Microsoft® SQL Server™ database. (In a two-tier application, the middle tier and data source tier are combined.)

These tiers don't necessarily correspond to physical locations on the network. For example, all three tiers may exist on only two computers. One computer could be a Microsoft® Windows® 95 computer running Microsoft® Internet Explorer 4.0 as its browser. The second computer could be a Windows NT Server computer running both Internet Information Server and Microsoft SQL Server. Designing applications this way gives you greater flexibility when deploying processes and data on the network for maximum performance and ease of maintenance.


How a Remote Data Service Application Works

When you create a Remote Data Service application, you can partition your application into two or three logical tiers. The following illustration shows how a Web-based RDS application handles a user request to display information from a database. The client-side components are typically hosted in an Internet Explorer browser, using HTTP to communicate with the server components. Internet Explorer 4.0 already includes the RDS client components, thus simplifying your deployment.

Once the user enters a request, the client-side RDS components send the query to the Web server. The server-side RDS components process the request and send it to the DBMS. The DBMS responds to the request, sending back the data. The RDS components on the Web server transform that data into an ADO Recordset object. The data is converted for transport to the client and sent back across the network to the client computer. It may be displayed in a data-aware control, such as a text box or grid, that is bound to the data by the RDS.DataControl object. One RDS.DataControl can channel data to many data-aware controls.

The resulting data is cached on the client computer, reducing the number of connections to the Web and making it easier for a user to manipulate the data. The only calls requiring a trip to the server are calls to the business object (such as updates to the data server or requests for new data).


Related Technologies

Many other technologies interact with Remote Data Service or are used in its implementation.

OLE DB For more information about using OLE DB, see the OLE DB Web site at http://www.microsoft.com/data/.

Internet Information Server For more information about Microsoft® Internet Information Server (IIS) or Active Server Pages (ASP), see the IIS Web site at http://www.microsoft.com/iis. For information about connection pooling, see the following:

  • Connection Pooling Options

Microsoft Transaction Server For more information about Microsoft® Transaction Server®, see the MTS Web site at http://www.microsoft.com/transaction/. For information about business objects in Microsoft Transaction Server, see the following:

  • Microsoft Transaction Server Resource Dispensers

Microsoft SQL Server For more information about Microsoft SQL Server, see the SQL Server Web site at http://www.microsoft.com/sql/. For information about using SQL Server with RDS, see the following:

  • Performance and Stability with Connection Pooling

  • Ensuring Sufficient TempDB Space

  • Minimizing Log File Space Usage

Microsoft Internet Explorer For more information about Microsoft Internet Explorer, see the Internet Explorer Web page at http://www.microsoft.com/ie/ and the Microsoft Internet Client SDK Web page at http://www.microsoft.com/msdn/sdk/inetsdk/asetup/. For information about data binding and bound controls, see the following:

  • Displaying Data through a Bound Control

Microsoft Windows NT Server For more information about Microsoft Windows NT Server and NT Security, see the NT Web page at http://www.microsoft.com/ntserver/. For information about NT Security and RDS, see the following:

  • Security and your Web Server


Developing Remote Data Service Applications

When you write code for your Web-based data access application, you need to understand the various components involved if you want to use the Remote Data Service’s data binding and remoting features.

The previous section, Understanding Remote Data Service Applications, introduces the architecture of a three-tiered RDS application, and explains how the client-side and server-side components communicate with each other to send data between clients and servers.

This section contains information about:

  • Getting a Recordset to the Client

  • Passing Updated Recordset Objects to the Middle Tier

  • Defining a Recordset


Getting a Recordset to the Client

There are three ways to pass a Recordset back from your server to the client with RDS. You can:

  • Use the RDS.DataControl methods and properties that automatically call the RDSServer.DataFactory object.

  • Manually call the RDSServer.DataFactory object.

  • Create a custom ActiveX DLL that performs data access functions.

This section explains how to pass Recordset objects using any of these methods.


Getting a Recordset with the RDS.DataControl Object

You can open a disconnected Recordset by setting the RDS.DataControl object's Connect, Server, and SQL properties.

The following code shows how to set these properties at design time:

<OBJECT CLASSID="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33" ID="ADC1">
   <PARAM NAME="SQL" VALUE="Select * from Products">
   <PARAM NAME="Connect" VALUE="DSN=AdvWorks;">
   <PARAM NAME="Server" VALUE="http://SalesWeb/">
</OBJECT>

Calling the Refresh method after setting these properties on the RDS.DataControl automatically calls the RDSServer.DataFactory object "behind the scenes," and Remote Data Service returns a Recordset object to the client. You don't have to actually write any code to use the RDSServer.DataFactory, but if you do want to do this, see "Getting a Recordset with the RDSServer.DataFactory Object."


Getting a Recordset with the RDSServer.DataFactory Object

Remote Data Service contains a server-side business object (ActiveX® DLL) called RDSServer.DataFactory that sends commands to a data source and passes the results back across the Internet or an intranet for you. RDSServer.DataFactory is the default ActiveX DLL that you can use to provide live data on your Web page with little programming.

The following example shows how to call the RDSServer.DataFactory object from a VBScript Web page. You use the RDS.DataSpace object on the client to create an instance of the RDSServer.DataFactory object on the server.

<HTML>
<HEAD></HEAD>
<BODY>

<!-- RDS.DataControl -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33" ID=ADC1>
</OBJECT>
<!-- RDS.DataSpace -->
<OBJECT ID="ADS1" WIDTH=1 HEIGHT=1
  CLASSID="CLSID:BD96C556-65A3-11D0-983A-00C04FC29E36">
</OBJECT>
.
.
.
<SCRIPT LANGUAGE="VBScript">
Option Explicit
Sub Window_OnLoad()
  Dim ADF1, myRS
  Set ADF1 = ADS1.CreateObject("RDSServer.DataFactory", _
  "http://<%=Request.ServerVariables("SERVER_NAME")%>")
  Set myRS = _
  ADF1.Query("DSN=pubs;UID=sa;PWD=permission;", _
  "Select * From Authors")
  ' Assign the returned recordset to SourceRecordset.
  ADC1.SourceRecordset = myRS
End Sub
</SCRIPT>
</BODY>
</HTML>


Getting a Recordset with a Custom Business Object

If you don't want to use the RDSServer.DataFactory object to pass Recordset objects back to the client, you can create your own custom business object that will run on the server. The DLL (dynamic-link library) can be any generic Automation object created with Microsoft® Visual Basic®, Microsoft® Visual C++®, and so forth, or a server-side HTML page with Active Server Pages scripting code. Clients and Web front-end applications call the business objects to perform a particular function, and those middle-tier business objects in turn can communicate with back-end databases.

The custom DLLs could also contain methods that aren't provided by the simple RDSServer.DataFactory ActiveX DLL. These methods don't have to be related to data access—they could just encompass a business rule.

This section contains information about:

  • Writing Code to Pass Recordset Objects with a Custom ActiveX DLL


Writing Code to Pass Recordset Objects with a Custom ActiveX DLL

The following client Microsoft® Visual Basic®, Scripting Edition code performs the same action as the previous RDSServer.DataFactory code, except that it uses a custom business object. You still use the RDS.DataSpace object on the client to create an instance of the business object (in this case, MyCustomBusinessObject) on the server.

<HTML>
<HEAD></HEAD>
<BODY>

<!-- RDS.DataControl -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33" ID=ADC1>
</OBJECT>
<!-- RDS.DataSpace -->
<OBJECT ID="ADS1" WIDTH=1 HEIGHT=1
  CLASSID="CLSID:BD96C556-65A3-11D0-983A-00C04FC29E36">
</OBJECT>
.
.
.
<SCRIPT LANGUAGE="VBScript">
Option Explicit
Sub GetRecords()
  Dim objMyCustomBusinessObject, myRS
  Set objMyCustomBusinessObject = _
  ADS1.CreateObject("MyCustomBusinessObject", _
  "http://<%=Request.ServerVariables("SERVER_NAME")%>")
  ' Assume MyCustomBusinessObject has a method called
  ' GetData that takes connection string and SQL
  ' parameters.
  Set myRS = _
  objCustomBusinessObject.GetData _
  ("DSN=pubs;UID=sa;PWD=permission;", _
  "Select * From Authors")
  ' Assign the returned recordset to SourceRecordset.
  ADC1.SourceRecordset = myRS
End Sub
</SCRIPT>
</BODY>
</HTML>

Assuming you use Visual Basic to create the MyCustomBusinessObject ActiveX DLL that is located on the middle tier, the code in the GetData method of the MyCustomBusinessObject class could look something like this. Notice that you can use ActiveX® Data Objects (ADO) directly.

' Returns an ADO resultset.
Public Function GetData(szCnStr As String, szSQL _
  As String) As Object

  Dim cn As New ADODB.Connection
  Dim rs As New ADODB.Recordset

  cn.Open szCnStr
  ' The ADODB.Recordset should generate Recordset
  ' objects that can be disconnected and later
  ' reconnected to process batch updates.
  rs.CursorLocation = adUseClientBatch
  ' Using the Unspecified parameters, an ADO/R
  ' recordset is returned.
  rs.Open szSQL, cn, _
  adOpenUnspecified, adLockUnspecified, _
  adCmdUnspecified
  Set GetData = rs
End Function

Tips

  • Always place one simple method in your server component to test for minimum functionality before attempting to pass Recordset objects back.

  • Build a simple client application to test your server component before deploying and testing it with Internet Explorer.

  • It is easier to develop your application on a local test Web server. You will need to copy and register the .dll on the test server after each compile.

  • The DSN passed to your business object will need to be a System DSN on your server. If it doesn't exist or is set up improperly, your component will fail. It is a good idea to test the DSN on the server with another ODBC application such as MSQuery to make sure the DSN is set up properly.

  • Method names on custom business objects cannot exceed 255 characters. This allows compatibility across all RDS-supported protocols (HTTP, HTTPS, DCOM, and running in-process).

  • If you used Visual Basic to create a custom business object that uses early binding with the ADOR 1.0 type library, you should rebuild your custom business object to use the ADOR 2.0 type library.


Passing Updated Recordsets to the Middle Tier

Passing Updated Recordset Objects to the Middle Tier

You can pass updated Recordset objects from client computers to the middle tier and the database server by using:

  • The RDS.DataControl object.

  • ADO with a middle-tier custom business object.


Using RDS.DataControl to Pass Updated Disconnected Recordset Objects Back to the Middle Tier

Data-bound controls enable the user to visually edit, add, or delete records. All changes by the user are stored locally until the user explicitly submits or cancels the update.

Typically, you will bind a grid control to an RDS.DataControl object, and then add, edit, and delete records in the client-side Recordset via the user interface. After you update the client-side data, you need to save the changed information to the database by using the SubmitChanges method with the RDS.DataControl object. The SubmitChanges method submits pending changes of the locally cached updatable Recordset to the OLE DB data source specified in the RDS.DataControl object's Connect property.

The following code example shows how to do this:

Sub Update_OnClick
   ADC1.SubmitChanges
End Sub

Only the changed records are sent for modification, and either all of the changes succeed or all of them fail together.

You can also include a Cancel button to cancel changes to the Recordset:

Sub Cancel_OnClick
   ADC1.CancelUpdate
End Sub

Notes

  • The Connect, Server, and SQL properties must be set before you can use the SubmitChanges method with the RDS.DataControl object. These properties are used to reconnect to the data source.

  • If you call the CancelUpdate method after you have called SubmitChanges for the same Recordset object, the CancelUpdate call fails because the changes have already been committed.


Using ADO to Pass Recordset Objects to the Middle Tier

You can use the ADOR.Recordset object to marshal recordsets from a client Web page to a middle-tier business object. For example, suppose a user connects to a virtual shopping mall and selects a number of items to purchase. The selected items appear in the virtual shopping cart that is implemented with the RDS.DataControl object and buffered in a rowset. When the client clicks the purchase button, an ADOR.Recordset object is created and passed to an application server as an input parameter to a business function (ApplyUpdates). This causes the Recordset to be marshaled across to the server. The ApplyUpdates business function then connects to the Sales database and applies the updates.

' Code on a client Web page.
Sub PurchaseItem_OnClick
   Set rst = ADC1.Recordset

' The following option tells the recordset to only send
' back changed records when updating. This makes the roundtrips
' more lightweight.
   rst.MarshalOptions = adMarshalModifiedOnly

' Call the ApplyUpdates function on the MyObj
' business object and pass the ador.Recordset
' object as an input parameter.
   MyObj.ApplyUpdates rst

End Sub

' VB code in the business object.
' ApplyUpdates is a method in a
' middle-tier business object.
Sub ApplyUpdates(rst As ADOR.Recordset)

   rst.ActiveConnection =  _
      "DSN=SalesDB;UID=SMgr;PWD=password"

' Save the changed records.
   rst.UpdateBatch

End Sub


Defining a Recordset

You can create an ADODB.Recordset object and specify the column information. You can then insert data into the Recordset object; the underlying rowset buffers the inserts.

The following code example shows how to define a Recordset by using the RDSServer.DataFactory object. You can also do this with the RDS.DataControl object.

Sub RsDefineShape()

   Dim vntRecordShape(3)
   Dim vntField1Shape(3)
   Dim vntField2Shape(3)
   Dim vntField3Shape(3)
   Dim vntField4Shape(3)

   ' For each field, specify the name,
   ' type, size, and nullability.

   vntField1Shape(0) = "Name"   ' Column name.
   vntField1Shape(1) = CInt(129)   ' Column type.
   vntField1Shape(2) = CInt(40)   ' Column size.
   vntField1Shape(3) = False      ' Nullable?

   vntField2Shape(0) = "Age"
   vntField2Shape (1) = CInt(3)
   vntField2Shape (2) = CInt(-1)
   vntField2Shape (3) = True

   vntField3Shape (0) = "DateOfBirth"
   vntField3Shape (1) = CInt(7)
   vntField3Shape (2) = CInt(-1)
   vntField3Shape (3) = True

   vntField4Shape (0) = "Balance"
   vntField4Shape (1) = CInt(6)
   vntField4Shape (2) = CInt(-1)
   vntField4Shape (3) = True

   ' Put all fields into an array of arrays.
   vntRecordShape(0) = vntField1Shape
   vntRecordShape(1) = vntField2Shape
   vntRecordShape(2) = vntField3Shape
   vntRecordShape(3) = vntField4Shape

   ' Use the RDSServer.DataFactory to create an empty
   ' recordset. It takes an array of variants where
   ' every element is itself another array of
   ' variants, one for every column required in the
   ' recordset.
   ' The elements of the inner array are the column's
   ' name, type, size and nullability.

   Dim NewRs

   ' You could just use the RDS.DataControl object
   ' instead of the RDSServer.DataFactory object. In
   ' that case, the following code would be Set NewRS
   ' = ADC1.CreateRecordset(vntRecordShape)
   Set NewRS = ADF.CreateRecordset(vntRecordShape)

   Dim fields(3)
   fields(0) = vntField1Shape(0)
   fields(1) = vntField2Shape (0)
   fields(2) = vntField3Shape (0)
   fields(3) = vntField4Shape (0)

   ' Populate the new recordset with data values.
   Dim fieldVals(3)

   ' Use AddNew to add the records.
   fieldVals(0) = "Joe"
   fieldVals(1) = 5
   fieldVals(2) = CDate(#1/5/96#)
   fieldVals(3) = 123.456
   NewRS.AddNew fields, fieldVals

   fieldVals(0) = "Mary"
   fieldVals(1) = 6
   fieldVals(2) = CDate(#6/5/96#)
   fieldVals(3) = 31
   NewRS.AddNew fields, fieldVals

   fieldVals(0) = "Alex"
   fieldVals(1) = 13
   fieldVals(2) = CDate(#1/6/96#)
   fieldVals(3) = 34.0001
   NewRS.AddNew fields, fieldVals

   fieldVals(0) = "Susan"
   fieldVals(1) = 13
   fieldVals(2) = CDate(#8/6/96#)
   fieldVals(3) = 0.0
   NewRS.AddNew fields, fieldVals

   NewRS.MoveFirst

   ' Set the newly created and populated Recordset to
   ' the SourceRecordset property of the
   ' RDS.DataControl to bind to visual controls.
   Set ADC1.SourceRecordset = NewRS

End Sub


Troubleshooting Remote Data Service

The following sections describe workarounds for specific errors.

  • "Internet Server Error: Access Denied"

  • "Unexpected Error" Message When Running the Sample Applications

  • Using the RDS.DataControl with the Sheridan Combo Box Control

  • Deadlocks With Read Repeatable Isolation Level

  • RDS.DataControl and Multiple Recordset Requests

  • Outdated Class IDs


"Internet Server Error: Access Denied"

If you get this error, it usually means that Microsoft® Internet Information Server (IIS) returned the following status:

HTTP_STATUS_DENIED 401

Make sure the directories accessed by IIS have proper permissions. RDS 1.5 can communicate with an IIS Web server running in any one of the three Password Authentication modes: Anonymous, Basic, or NT Challenge/Response. Unlike previous versions, the Allow Anonymous setting is no longer required. Also, the Web server must have permissions to the data source computer if it is a Windows NT® computer.


"Unexpected Error" Message When Running the Sample Applications

Server Checklist

  • If you reinstall IIS, you must reinstall Remote Data Service afterward.

  • If you are using Microsoft SQL Server as your back-end data source, use Microsoft SQL Server 6.5, Service Pack 2 or later.

  • Ensure that the ODBC DSNs are System DSNs and not User DSNs. The Anonymous user logging on through IIS can view only System DSNs.

  • Check that the anonymous account that your WWW service uses is a user on your domain that has NTFS permissions to all the relevant servers and directories. Finally, verify that the password for this anonymous account hasn't expired.

  • Because Remote Data Service is installed in the C:\Program Files\Common Files\System\MSADC directory, check that the Anonymous user from the IIS Service Manager can access this directory. It should have both Read and Execute access.

  • If you have trouble with Remote Data Service DLLs and sample applications, reregister the DLLs by using Regsvr32.exe.

  • If you are writing your own business objects, place your Active Server Pages script files (.asp) in a directory that gives the Anonymous user (in IIS) Execute permission.


Using the RDS.DataControl with the Sheridan Combo Box Control

The Sheridan combo box has two properties that can be bound to RDS.DataControl data. Just binding the combo box to RDS.DataControl doesn't automatically populate the "Text" portion, a nonbindable property that shows the currently selected item. As a result, old data may still be displayed after the Refresh method is called.

A workaround is to use code like either of the following two sample Microsoft® Visual Basic®, Scripting Edition Sub procedures. Both clear the Text property when the Refresh method is called. SSCombo is the name of the Sheridan combo box control in these examples.

Sub SSCombo_InitColumnProps()
   SSCombo.Text=""
End Sub

Sub Refresh_OnClick
   ADC1.Refresh
   SSCombo.Text=""
End Sub


Deadlocks With Read Repeatable Isolation Level

If a custom business object uses an isolation level of read repeatable to access a SQL Server, and the business object is called simultaneously by two clients that send a query and update in the same transaction, a deadlock is possible. Remote Data Service is built to allow one of the processes to time out to release the deadlock, but this will fail the update for that client.

You can add a registry entry on the Web server to modify the length of the timeout. The default is 30 seconds (or 30,000 milliseconds).

To modify the timeout value

  1. From the Start menu, click Run.

  2. Type RegEdit and click OK.

  3. In the Registry Editor, navigate to the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W3SVC\Parameters key.

  4. Select the Parameters key. From the Edit menu, point to New, and select DWORD Value.

  5. In the Name column, type ADCUpdateTimeout and press Enter.

  6. Double-click the new entry. In the Edit DWORD Value dialog box, enter the new value in milliseconds in the Value data box. The value must be greater than or equal to zero.


RDS.DataControl and Multiple Recordset Requests

If you query for multiple results, only the first Recordset is returned. If multiple result sets are needed, assign each to its own RDS.DataControl. An example of a query for multiple results could be "Select * from Authors, Select * from Topics".


Outdated Class IDs

If you get an error that an RDS.DataSpace or RDS.DataControl object doesn't load, make sure you are using the correct class ID. The class IDs for these objects have changed from version 1.0 and 1.1. The correct class IDs are listed as follows.

Object | Class ID
RDS.DataControl | BD96C556-65A3-11D0-983A-00C04FC29E33
RDS.DataSpace | BD96C556-65A3-11D0-983A-00C04FC29E36


AbsolutePage, PageCount, and PageSize Properties Example

This example uses the AbsolutePage, PageCount, and PageSize properties to display names and hire dates from the Employee table five records at a time.

Public Sub AbsolutePageX()

   Dim rstEmployees As ADODB.Recordset
   Dim strCnn As String
   Dim strMessage As String
   Dim intPage As Integer
   Dim intPageCount As Integer
   Dim intRecord As Integer

   ' Open a recordset using a client cursor
   ' for the employee table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstEmployees = New ADODB.Recordset
   ' Use client cursor to enable AbsolutePosition property.
   rstEmployees.CursorLocation = adUseClient
   rstEmployees.Open "employee", strCnn, , , adCmdTable

   ' Display names and hire dates, five records
   ' at a time.
   rstEmployees.PageSize = 5
   intPageCount = rstEmployees.PageCount
   For intPage = 1 To intPageCount
      rstEmployees.AbsolutePage = intPage
      strMessage = ""
      For intRecord = 1 To rstEmployees.PageSize
         strMessage = strMessage & _
            rstEmployees!fname & " " & _
            rstEmployees!lname & " " & _
            rstEmployees!hire_date & vbCr
         rstEmployees.MoveNext
         If rstEmployees.EOF Then Exit For
      Next intRecord
      MsgBox strMessage
   Next intPage
   rstEmployees.Close

End Sub


AbsolutePosition and CursorLocation Properties Example

This example demonstrates how the AbsolutePosition property can track the progress of a loop that enumerates all the records of a Recordset. It uses the CursorLocation property to enable the AbsolutePosition property by setting the cursor to a client cursor.

Public Sub AbsolutePositionX()

   Dim rstEmployees As ADODB.Recordset
   Dim strCnn As String
   Dim strMessage As String

   ' Open a recordset for the Employee table
   ' using a client cursor.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstEmployees = New ADODB.Recordset
   ' Use client cursor to enable AbsolutePosition property.
   rstEmployees.CursorLocation = adUseClient
   rstEmployees.Open "employee", strCnn, , , adCmdTable

   ' Enumerate Recordset.
   Do While Not rstEmployees.EOF
      ' Display current record information.
      strMessage = "Employee: " & rstEmployees!lName & vbCr & _
         "(record " & rstEmployees.AbsolutePosition & _
         " of " & rstEmployees.RecordCount & ")"
      If MsgBox(strMessage, vbOKCancel) = vbCancel _
         Then Exit Do
      rstEmployees.MoveNext
   Loop

   rstEmployees.Close

End Sub


ActiveConnection, CommandText, CommandTimeout, CommandType, Size, and Direction Properties Example

This example uses the ActiveConnection, CommandText, CommandTimeout, CommandType, Size, and Direction properties to execute a stored procedure.

Public Sub ActiveConnectionX()

   Dim cnn1 As ADODB.Connection
   Dim cmdByRoyalty As ADODB.Command
   Dim prmByRoyalty As ADODB.Parameter
   Dim rstByRoyalty As ADODB.Recordset
   Dim rstAuthors As ADODB.Recordset
   Dim intRoyalty As Integer
   Dim strAuthorID As String
   Dim strCnn As String

   ' Define a command object for a stored procedure.
   Set cnn1 = New ADODB.Connection
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn
   Set cmdByRoyalty = New ADODB.Command
   Set cmdByRoyalty.ActiveConnection = cnn1
   cmdByRoyalty.CommandText = "byroyalty"
   cmdByRoyalty.CommandType = adCmdStoredProc
   cmdByRoyalty.CommandTimeout = 15

   ' Define the stored procedure's input parameter.
   intRoyalty = Trim(InputBox( _
      "Enter royalty:"))
   Set prmByRoyalty = New ADODB.Parameter
   prmByRoyalty.Type = adInteger
   prmByRoyalty.Size = 3
   prmByRoyalty.Direction = adParamInput
   prmByRoyalty.Value = intRoyalty
   cmdByRoyalty.Parameters.Append prmByRoyalty

   ' Create a recordset by executing the command.
   Set rstByRoyalty = cmdByRoyalty.Execute()

   ' Open the Authors table to get author names for display.
   Set rstAuthors = New ADODB.Recordset
   rstAuthors.Open "authors", strCnn, , , adCmdTable

   ' Print current data in the recordset, adding
   ' author names from Authors table.
   Debug.Print "Authors with " & intRoyalty & _
      " percent royalty"
   Do While Not rstByRoyalty.EOF
      strAuthorID = rstByRoyalty!au_id
      Debug.Print , rstByRoyalty!au_id & ", ";
      rstAuthors.Filter = "au_id = '" & strAuthorID & "'"
      Debug.Print rstAuthors!au_fname & " " & _
         rstAuthors!au_lname
      rstByRoyalty.MoveNext
   Loop

   rstByRoyalty.Close
   rstAuthors.Close
   cnn1.Close

End Sub


ActualSize and DefinedSize Properties Example

This example uses the ActualSize and DefinedSize properties to display the defined size and actual size of a field.

Public Sub ActualSizeX()

   Dim rstStores As ADODB.Recordset
   Dim strCnn As String

   ' Open a recordset for the Stores table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstStores = New ADODB.Recordset
   rstStores.Open "stores", strCnn, , , adCmdTable

   ' Loop through the recordset displaying the contents
   ' of the stor_name field, the field's defined size,
   ' and its actual size.
   rstStores.MoveFirst

   Do Until rstStores.EOF
      MsgBox "Store name: " & rstStores!stor_name & _
      vbCr & "Defined size: " & _
      rstStores!stor_name.DefinedSize & _
      vbCr & "Actual size: " & _
      rstStores!stor_name.ActualSize & vbCr
      rstStores.MoveNext
   Loop

   rstStores.Close

End Sub


AddNew Method Example

This example uses the AddNew method to create a new record with the specified name.

Public Sub AddNewX()

   Dim cnn1 As ADODB.Connection
   Dim rstEmployees As ADODB.Recordset
   Dim strCnn As String
   Dim strID As String
   Dim strFirstName As String
   Dim strLastName As String
   Dim booRecordAdded As Boolean

   ' Open a connection.
   Set cnn1 = New ADODB.Connection
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=;"
   cnn1.Open strCnn

   ' Open Employee table.
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.CursorType = adOpenKeyset
   rstEmployees.LockType = adLockOptimistic
   rstEmployees.Open "employee", cnn1, , , adCmdTable

   ' Get data from the user. The employee ID must be formatted as
   ' first, middle, and last initial, five numbers, then M or F to
   ' signify the gender. For example, the employee id for Bill Sornsin
   ' would be "B-S55555M".
   strID = Trim(InputBox("Enter employee ID:"))
   strFirstName = Trim(InputBox("Enter first name:"))
   strLastName = Trim(InputBox("Enter last name:"))

   ' Proceed only if the user actually entered something
   ' for both the first and last names.
   If (strID <> "") And (strFirstName <> "") _
      And (strLastName <> "") Then

      rstEmployees.AddNew
      rstEmployees!emp_id = strID
      rstEmployees!fname = strFirstName
      rstEmployees!lname = strLastName
      rstEmployees.Update
      booRecordAdded = True

      ' Show the newly added data.
      MsgBox "New record: " & rstEmployees!emp_id & " " & _
         rstEmployees!fname & " " & rstEmployees!lname

   Else
      MsgBox "Please enter an employee ID, " & _
         "first name, and last name."
   End If

   ' Delete the new record because this is a demonstration.
   cnn1.Execute "DELETE FROM employee WHERE emp_id = '" & strID & "'"

   rstEmployees.Close
   cnn1.Close

End Sub

VBScript Version

The following is the same example written in VBScript to be used in an Active Server Page (ASP). To view this fully functional example, you need to create a system Data Source Name (DSN) called AdvWorks using the data source AdvWorks.mdb installed with IIS and located at C:\InetPub\ASPSamp\AdvWorks. This is a Microsoft Access database file. Use Find to locate the file Adovbs.inc and place it in the directory you plan to use. Cut and paste the following code to Notepad or another text editor and save it as AddNew.asp. You can view the result in any client browser.

To exercise the example, add a new fictional record in the HTML form. Click Add New. See the Delete method example to remove unwanted records.

<!-- #Include file="ADOVBS.INC" -->
<% Language = VBScript %>
<HTML><HEAD><TITLE>ADO Open Method</TITLE>
</HEAD><BODY>
<FONT FACE="MS SANS SERIF" SIZE=2>
<Center><H3>ADO AddNew Method</H3>
<!-- ADO Connection Object used to create recordset-->
<%
'Create and Open Connection Object
Set OBJdbConnection = Server.CreateObject("ADODB.Connection")
OBJdbConnection.Open "AdvWorks"
'Create and Open Recordset Object
Set RsCustomerList = Server.CreateObject("ADODB.Recordset")
RsCustomerList.ActiveConnection = OBJdbConnection
RsCustomerList.CursorType = adOpenKeyset
RsCustomerList.LockType = adLockOptimistic
RsCustomerList.Source = "Customers"
RsCustomerList.Open

%>
<!-- If this is first time page is open, Form collection will be empty when data is entered.

run AddNew method-->
<% If Not IsEmpty(Request.Form) Then
   If Not Request.Form("CompanyName") = "" Then
      RsCustomerList.AddNew
      RsCustomerList("CompanyName") = Request.Form("CompanyName")
      RsCustomerList("ContactLastName") = Request.Form("LastName")
      RsCustomerList("ContactFirstName") = Request.Form("FirstName")
      RsCustomerList("PhoneNumber") = Request.Form("PhoneNumber")
      RsCustomerList("City") = Request.Form("City")
      RsCustomerList("StateOrProvince") = Request.Form("State")
      RsCustomerList.Update
      RsCustomerList.MoveFirst

   End If
End If
%>

<TABLE COLSPAN=8 CELLPADDING=5 BORDER=0>

<!-- BEGIN column header row for Customer Table-->

<TR><TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Company Name</FONT></TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Contact Name</FONT></TD>
<TD ALIGN=CENTER WIDTH=150 BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Phone Number</FONT></TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>City</FONT></TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>State/Province</FONT></TD></TR>
<!--Display ADO Data from Customer Table one row on each pass through recordset-->
<% Do While Not RsCustomerList.EOF %>
  <TR><TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RSCustomerList("CompanyName")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("ContactLastName") & ", " %>
  <%= RScustomerList("ContactFirstName") %>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
   <%= RScustomerList("PhoneNumber")%>
 </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("City")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("StateOrProvince")%>
  </FONT></TD></TR>
<!-- Next Row = Record Loop and add to row html table-->
<%
RScustomerList.MoveNext
Loop
%>

</TABLE><HR>
<!-- Form to enter new record posts variables back to this page -->
<Table>
<Form Method = Post Action="AddNew.asp" Name=Form>
<TR><TD><P>Company Name:</TD>
<TD><Input Type="Text" Size="50" Name="CompanyName" Value = ""></P></TD>
<TR><TD><P>Contact First Name:</TD>
<TD><Input Type="Text" Size="50" Name="FirstName" Value = ""></P></TD>
<TR><TD><P>Contact Last Name:</TD>
<TD><Input Type="Text" Size="50" Name="LastName" Value = ""></P></TD>
<TR><TD><P>Contact Phone:</TD>
<TD><Input Type="Text" Size="50" Name="PhoneNumber" Value = ""></P></TD>
<TR><TD><P>City:</TD>
<TD><Input Type="Text" Size="50" Name="City" Value = ""></P></TD>
<TR><TD><P>State / Province:</TD>
<TD><Input Type="Text" Size="5" Name="State" Value = ""></P></TD>
<TR><TD><Input Type="Submit" Value="Add New "><Input Type="Reset" Value="Reset Form">
</Form></Table></Center></FONT>
<%'Show location of DSN data source
Response.Write(OBJdbConnection)
%>
<Script Language = "VBScript">
Sub Form_OnSubmit
   MsgBox "Sending New Record to Server",,"ADO-ASP _Example"
End Sub
</Script>
</BODY></HTML>


Append and CreateParameter Methods Example

This example uses the Append and CreateParameter methods to execute a stored procedure with an input parameter.

Public Sub AppendX()

   Dim cnn1 As ADODB.Connection
   Dim cmdByRoyalty As ADODB.Command
   Dim prmByRoyalty As ADODB.Parameter
   Dim rstByRoyalty As ADODB.Recordset
   Dim rstAuthors As ADODB.Recordset
   Dim intRoyalty As Integer
   Dim strAuthorID As String
   Dim strCnn As String

   ' Open connection.
   Set cnn1 = New ADODB.Connection
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn
   cnn1.CursorLocation = adUseClient

   ' Open command object with one parameter.
   Set cmdByRoyalty = New ADODB.Command
   cmdByRoyalty.CommandText = "byroyalty"
   cmdByRoyalty.CommandType = adCmdStoredProc

   ' Get parameter value and append parameter.
   intRoyalty = Trim(InputBox("Enter royalty:"))
   Set prmByRoyalty = cmdByRoyalty.CreateParameter("percentage", _
      adInteger, adParamInput)
   cmdByRoyalty.Parameters.Append prmByRoyalty
   prmByRoyalty.Value = intRoyalty

   ' Create recordset by executing the command.
   Set cmdByRoyalty.ActiveConnection = cnn1
   Set rstByRoyalty = cmdByRoyalty.Execute

   ' Open the Authors table to get author names for display.
   Set rstAuthors = New ADODB.Recordset
   rstAuthors.Open "authors", cnn1, , , adCmdTable

   ' Print current data in the recordset, adding
   ' author names from Authors table.
   Debug.Print "Authors with " & intRoyalty & " percent royalty"
   Do While Not rstByRoyalty.EOF
      strAuthorID = rstByRoyalty!au_id
      Debug.Print "   " & rstByRoyalty!au_id & ", ";
      rstAuthors.Filter = "au_id = '" & strAuthorID & "'"
      Debug.Print rstAuthors!au_fname & " " & rstAuthors!au_lname
      rstByRoyalty.MoveNext
   Loop

   rstByRoyalty.Close
   rstAuthors.Close
   cnn1.Close

End Sub


AppendChunk and GetChunk Methods Example

This example uses the AppendChunk and GetChunk methods to fill an image field with data from another record.

Public Sub AppendChunkX()

   Dim cnn1 As ADODB.Connection
   Dim rstPubInfo As ADODB.Recordset
   Dim strCnn As String
   Dim strPubID As String
   Dim strPRInfo As String
   Dim lngOffset As Long
   Dim lngLogoSize As Long
   Dim varLogo As Variant
   Dim varChunk As Variant

   Const conChunkSize = 100

   ' Open a connection.
   Set cnn1 = New ADODB.Connection
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn

   ' Open the pub_info table.
   Set rstPubInfo = New ADODB.Recordset
   rstPubInfo.CursorType = adOpenKeyset
   rstPubInfo.LockType = adLockOptimistic
   rstPubInfo.Open "pub_info", cnn1, , , adCmdTable

   ' Prompt for a logo to copy.
   strMsg = "Available logos are : " & vbCr & vbCr
   Do While Not rstPubInfo.EOF
      strMsg = strMsg & rstPubInfo!pub_id & vbCr & _
         Left(rstPubInfo!pr_info, InStr(rstPubInfo!pr_info, ",") - 1) & _
         vbCr & vbCr
      rstPubInfo.MoveNext
   Loop
   strMsg = strMsg & "Enter the ID of a logo to copy:"
   strPubID = InputBox(strMsg)

   ' Copy the logo to a variable in chunks.
   rstPubInfo.Filter = "pub_id = '" & strPubID & "'"
   lngLogoSize = rstPubInfo!logo.ActualSize
   Do While lngOffset < lngLogoSize
      varChunk = rstPubInfo!logo.GetChunk(conChunkSize)
      varLogo = varLogo & varChunk
      lngOffset = lngOffset + conChunkSize
   Loop

   ' Get data from the user.
   strPubID = Trim(InputBox("Enter a new pub ID:"))
   strPRInfo = Trim(InputBox("Enter descriptive text:"))

   ' Add a new record, copying the logo in chunks.
   rstPubInfo.AddNew
   rstPubInfo!pub_id = strPubID
   rstPubInfo!pr_info = strPRInfo

   lngOffset = 0 ' Reset offset.
   Do While lngOffset < lngLogoSize
      varChunk = LeftB(RightB(varLogo, lngLogoSize - lngOffset), _
         conChunkSize)
      rstPubInfo!logo.AppendChunk varChunk
      lngOffset = lngOffset + conChunkSize
   Loop
   rstPubInfo.Update

    ' Show the newly added data.
   MsgBox "New record: " & rstPubInfo!pub_id & vbCr & _
      "Description: " & rstPubInfo!pr_info & vbCr & _
      "Logo size: " & rstPubInfo!logo.ActualSize

   ' Delete new record because this is a demonstration.
   rstPubInfo.Requery
   cnn1.Execute "DELETE FROM pub_info " & _
      "WHERE pub_id = '" & strPubID & "'"

   rstPubInfo.Close
   cnn1.Close

End Sub


Attributes and Name Properties Example

This examples displays the value of the Attributes property for Connection, Field, and Property objects. It uses the Name property to display the name of each Field and Property object.

Public Sub AttributesX

   Dim cnn1 As ADODB.Connection
   Dim rstEmployees As ADODB.Recordset
   Dim fldLoop As ADODB.Field
   Dim proLoop As ADODB.Property
   Dim strCnn As String

   ' Open connection and recordset.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set cnn1 = New ADODB.Connection
   cnn1.Open strCnn
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.Open "employee", cnn1, , , adCmdTable

   ' Display the attributes of the connection.
   Debug.Print "Connection attributes = " & _
      cnn1.Attributes

   ' Display the attributes of the Employee table's
   ' fields.
   Debug.Print "Field attributes:"
   For Each fldLoop In rstEmployees.Fields
      Debug.Print "   " & fldLoop.Name & " = " & _
         fldLoop.Attributes
   Next fldLoop

   ' Display Fields of the Employee table which are NULLABLE
   Debug.Print "NULLABLE Fields:"
   For Each fldLoop In rstEmployees.Fields
      If CBool(fldLoop.Attributes And adFldIsNullable) Then
         Debug.Print "   " & fldLoop.Name
      End If
   Next fldLoop

   ' Display the attributes of the Employee table's
   ' properties.
   Debug.Print "Property attributes:"
   For Each proLoop In rstEmployees.Properties
      Debug.Print "   " & proLoop.Name & " = " & _
         proLoop.Attributes
   Next proLoop

   rstEmployees.Close
   cnn1.Close

End Sub


BeginTrans, CommitTrans, and RollbackTrans Methods Example

This example changes the book type of all psychology books in the Titles table of the database. After the BeginTrans method starts a transaction that isolates all the changes made to the Titles table, the CommitTrans method saves the changes. You can use the Rollback method to undo changes that you saved using the Update method.

Public Sub BeginTransX()

   Dim cnn1 As ADODB.Connection
   Dim rstTitles As ADODB.Recordset
   Dim strCnn As String
   Dim strTitle As String
   Dim strMessage As String

   ' Open connection.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set cnn1 = New ADODB.Connection
   cnn1.Open strCnn

   ' Open Titles table.
   Set rstTitles = New ADODB.Recordset
   rstTitles.CursorType = adOpenDynamic
   rstTitles.LockType = adLockPessimistic
   rstTitles.Open "titles", cnn1, , , adCmdTable

   rstTitles.MoveFirst
   cnn1.BeginTrans

   ' Loop through recordset and ask user if she wants
   ' to change the type for a specified title.
   Do Until rstTitles.EOF
      If Trim(rstTitles!Type) = "psychology" Then
         strTitle = rstTitles!Title
         strMessage = "Title: " & strTitle & vbCr & _
         "Change type to self help?"

         ' Change the title for the specified
         ' employee.
         If MsgBox(strMessage, vbYesNo) = vbYes Then
            rstTitles!Type = "self_help"
            rstTitles.Update
         End If
      End If

         rstTitles.MoveNext
   Loop

   ' Ask if the user wants to commit to all the
   ' changes made above.
   If MsgBox("Save all changes?", vbYesNo) = vbYes Then
      cnn1.CommitTrans
   Else
      cnn1.RollbackTrans
   End If

   ' Print current data in recordset.
   rstTitles.Requery
   rstTitles.MoveFirst
   Do While Not rstTitles.EOF
      Debug.Print rstTitles!Title & " - " & rstTitles!Type
      rstTitles.MoveNext
   Loop

   ' Restore original data because this
   ' is a demonstration.
   rstTitles.MoveFirst
   Do Until rstTitles.EOF
      If Trim(rstTitles!Type) = "self_help" Then
         rstTitles!Type = "psychology"
         rstTitles.Update
      End If
      rstTitles.MoveNext
   Loop

   rstTitles.Close
   cnn1.Close

End Sub


BOF, EOF, and Bookmark Properties Example

This example uses the BOF and EOF properties to display a message if a user tries to move past the first or last record of a Recordset. It uses the Bookmark property to let the user flag a record in a Recordset and return to it later.

Public Sub BOFX()

   Dim rstPublishers As ADODB.Recordset
   Dim strCnn As String
   Dim strMessage As String
   Dim intCommand As Integer
   Dim varBookmark As Variant

   ' Open recordset with data from Publishers table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstPublishers = New ADODB.Recordset
   rstPublishers.CursorType = adOpenStatic
   ' Use client cursor to enable AbsolutePosition property.
   rstPublishers.CursorLocation = adUseClient
   rstPublishers.Open "SELECT pub_id, pub_name FROM publishers " & _
      "ORDER BY pub_name", strCnn, , , adCmdText

   rstPublishers.MoveFirst

   Do While True
      ' Display information about current record
      ' and get user input.
      strMessage = "Publisher: " & rstPublishers!pub_name & _
         vbCr & "(record " & rstPublishers.AbsolutePosition & _
         " of " & rstPublishers.RecordCount & ")" & vbCr & vbCr & _
         "Enter command:" & vbCr & _
         "[1 - next / 2 - previous /" & vbCr & _
         "3 - set bookmark / 4 - go to bookmark]"
      intCommand = Val(InputBox(strMessage))

      Select Case intCommand
         ' Move forward or backward, trapping for BOF
         ' or EOF.
         Case 1
            rstPublishers.MoveNext
            If rstPublishers.EOF Then
               MsgBox "Moving past the last record." & _
                  vbCr & "Try again."
               rstPublishers.MoveLast
            End If
         Case 2
            rstPublishers.MovePrevious
            If rstPublishers.BOF Then
               MsgBox "Moving past the first record." & _
                  vbCr & "Try again."
               rstPublishers.MoveFirst
            End If

         ' Store the bookmark of the current record.
         Case 3
            varBookmark = rstPublishers.Bookmark

         ' Go to the record indicated by the stored
         ' bookmark.
         Case 4
            If IsEmpty(varBookmark) Then
               MsgBox "No Bookmark set!"
            Else
               rstPublishers.Bookmark = varBookmark
            End If

         Case Else
            Exit Do
      End Select

   Loop

   rstPublishers.Close

End Sub

This example uses the Bookmark and Filter properties to create a limited view of the Recordset. Only records referenced by the array of bookmarks are accessible.

Public Sub BOFX2()

Dim rs As New ADODB.Recordset
Dim bmk(10)

rs.CursorLocation = adUseClient
rs.ActiveConnection = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=;"

rs.Open "select * from authors", , adOpenStatic, adLockBatchOptimistic
Debug.Print "Number of records before filtering: ", rs.RecordCount

ii = 0
While rs.EOF <> True And ii < 11
    bmk(ii) = rs.Bookmark
    ii = ii + 1
    rs.Move 2
Wend
rs.Filter = bmk
Debug.Print "Number of records after filtering: ", rs.RecordCount

rs.MoveFirst
While rs.EOF <> True
    Debug.Print rs.AbsolutePosition, rs("au_lname")
    rs.MoveNext
Wend

End Sub


CacheSize Property Example

This example uses the CacheSize property to show the difference in performance for an operation performed with and without a 30-record cache.

Public Sub CacheSizeX()

   Dim rstRoySched As ADODB.Recordset
   Dim strCnn As String
   Dim sngStart As Single
   Dim sngEnd As Single
   Dim sngNoCache As Single
   Dim sngCache As Single
   Dim intLoop As Integer
   Dim strTemp As String

   ' Open the RoySched table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstRoySched = New ADODB.Recordset
   rstRoySched.Open "roysched", strCnn, , , adCmdTable

   ' Enumerate the Recordset object twice and record
   ' the elapsed time.
   sngStart = Timer

   For intLoop = 1 To 2
      rstRoySched.MoveFirst

      Do While Not rstRoySched.EOF
         ' Execute a simple operation for the
         ' performance test.
         strTemp = rstRoySched!title_id
         rstRoySched.MoveNext
      Loop
   Next intLoop

   sngEnd = Timer
   sngNoCache = sngEnd - sngStart

   ' Cache records in groups of 30 records.
   rstRoySched.MoveFirst
   rstRoySched.CacheSize = 30
   sngStart = Timer

   ' Enumerate the Recordset object twice and record
   ' the elapsed time.
   For intLoop = 1 To 2

      rstRoySched.MoveFirst
      Do While Not rstRoySched.EOF
         ' Execute a simple operation for the
         ' performance test.
         strTemp = rstRoySched!title_id
         rstRoySched.MoveNext
      Loop
   Next intLoop

   sngEnd = Timer
   sngCache = sngEnd - sngStart

   ' Display performance results.
   MsgBox "Caching Performance Results:" & vbCr & _
      "   No cache: " & Format(sngNoCache, _
      "##0.000") & " seconds" & vbCr & _
      "   30-record cache: " & Format(sngCache, _
      "##0.000") & " seconds"
   rstRoySched.Close

End Sub


Cancel Method Example

This example uses the Cancel method to cancel a command executing on a connection object if the connection is busy.

Public Sub CancelX()

   Dim cnn1 As ADODB.Connection
   Dim strCnn As String
   Dim strCmdChange As String
   Dim strCmdRestore As String
   Dim booChanged As Boolean

   ' Open a connection.
   Set cnn1 = New ADODB.Connection
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn

   ' Define command strings.
   strCmdChange = "UPDATE titles SET type = 'self_help' " & _
      "WHERE type = 'psychology'"
   strCmdRestore = "UPDATE titles SET type = 'psychology' " & _
      "WHERE type = 'self_help'"

   ' Begin a transaction, then execute a command asynchronously.
   cnn1.BeginTrans
   cnn1.Execute strCmdChange, , adAsyncExecute

   ' do something else for a little while – this could be changed
      For i = 1 To 10
         i = i + i
         Debug.Print i
      Next i

   ' If the command has NOT completed, cancel the execute
   ' and roll back the transaction. Otherwise, commit the
   ' transaction.
   If CBool(cnn1.State And adStateExecuting) Then
      cnn1.Cancel
      cnn1.RollbackTrans
      booChanged = False
      MsgBox "Update canceled."
   Else
      cnn1.CommitTrans
      booChanged = True
      MsgBox "Update complete."
   End If

   ' If the change was made, restore the data
   ' because this is a demonstration.
   If booChanged Then
      cnn1.Execute strCmdRestore
      MsgBox "Data restored."
   End If

   cnn1.Close

End Sub


Cancel Method Example (VBScript)

The following example shows how to read the Cancel method at run time in VBScript code.

<Script Language="VBScript">
<!--
Sub cmdCancelAsync
ADC.Cancel
' Terminates currently running AsyncExecute,
' ReadyState property set to adcReadyStateLoaded,
' Recordset set to Nothing
End Sub
-->
</Script>


CancelUpdate Method Example (VBScript)

To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi6.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples</H2>
<HR><H3>Remote Data Service SubmitChanges and CancelUpdate Methods</H3>

<!-- RDS.DataControl with parameters set at design time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
   <PARAM NAME="SQL" VALUE="Select * from Employee for browse">
   <PARAM NAME="SERVER" VALUE="http://<%=Request.ServerVariables("SERVER_NAME")%>">
   <PARAM NAME="CONNECT" VALUE="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;">
</OBJECT>

<Object classid="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE="Remote Data Service Run Time">
</OBJECT>
<HR>
<INPUT TYPE=BUTTON NAME="SubmitChange" VALUE="Submit-Changes"><INPUT TYPE=BUTTON NAME="CancelChange" VALUE="Cancel-Update"><BR>
<H4>Add a new person or alter a current entry on the grid. Move off that Row. <BR>
Submit the Changes to your DBMS or cancel the updates. </H4>
</Center>
<Script Language="VBScript">
<!--
' Set parameters of RDS.DataControl at Run Time
Sub SubmitChange_OnClick
   ADC.SubmitChanges
   ADC.Refresh
End Sub

Sub CancelUpdate_OnClick
   ADC.CancelUpdate
End Sub
-->
</Script>


Clone Method Example (Visual Basic)

This example uses the Clone method to create copies of a Recordset and then lets the user position the record pointer of each copy independently.

Public Sub CloneX()

   Dim arstStores(1 To 3) As ADODB.Recordset
   Dim intLoop As Integer
   Dim strSQL As String
   Dim strCnn As String
   Dim strMessage As String
   Dim strFind As String

   ' Assign SQL statement and connection string to variables.
   strSQL = "SELECT stor_name FROM Stores " & _
      "ORDER BY stor_name"
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "

   ' Open recordset as a static cursor type recordset.
   Set arstStores(1) = New ADODB.Recordset
   arstStores(1).CursorType = adOpenStatic
   arstStores(1).LockType = adLockBatchOptimistic
   arstStores(1).Open strSQL, strCnn, , , adCmdText

   ' Create two clones of the original Recordset.
   Set arstStores(2) = arstStores(1).Clone
   Set arstStores(3) = arstStores(1).Clone

   Do While True

      ' Loop through the array so that on each pass,
      ' the user is searching a different copy of the
      ' same Recordset.
      For intLoop = 1 To 3

         ' Ask for search string while showing where
         ' the current record pointer is for each Recordset.
         strMessage = _
            "Recordsets from stores table:" & vbCr & _
            "  1 - Original - Record pointer at " & _
            arstStores(1)!stor_name & vbCr & _
            "  2 - Clone - Record pointer at " & _
            arstStores(2)!stor_name & vbCr & _
            "  3 - Clone - Record pointer at " & _
            arstStores(3)!stor_name & vbCr & _
            "Enter search string for #" & intLoop & ":"
         strFind = Trim(InputBox(strMessage))
         If strFind = "" Then Exit Do

         ' Find the search string; if there's no
         ' match, jump to the last record.
         arstStores(intLoop).Filter = "stor_name >= '" & strFind & "'"
         If arstStores(intLoop).EOF Then
            arstStores(intLoop).Filter = adFilterNone
            arstStores(intLoop).MoveLast
         End If

      Next intLoop

   Loop

   arstStores(1).Close
   arstStores(2).Close
   arstStores(3).Close

End Sub

VBScript Version

Here is the same example written in VBScript to be used in an Active Server Page (ASP). To view this fully functional example, you need to create a system Data Source Name (DSN) called AdvWorks using the data source AdvWorks.mdb installed with IIS and located at C:\InetPub\ASPSamp\AdvWorks. This is a Microsoft Access database file. Use Find to locate the file Adovbs.inc and place it in the directory you plan to use. Cut and paste the following code to Notepad or another text editor and save it as Clone.asp. You can view the result in any client browser.

To exercise the example, change the line RsCustomerList.Source = "Customers" to RsCustomerList.Source = "Products" to count a larger table.

<!-- #Include file="ADOVBS.INC" -->
<% Language = VBScript %>
<HTML><HEAD>
<TITLE>ADO Clone Method</TITLE>
</HEAD><BODY> <Center>
<H3>ADO Clone Method</H3>
<!--- ADO Connection Object used to create recordset-->
<%
'Create and open Connection object
Set OBJdbConnection = Server.CreateObject("ADODB.Connection")
OBJdbConnection.Open "AdvWorks"
'Create and open Recordset object
Set RsCustomerList = Server.CreateObject("ADODB.Recordset")
RsCustomerList.ActiveConnection = OBJdbConnection
RsCustomerList.CursorType = adOpenKeyset
RsCustomerList.LockType = adLockOptimistic
RsCustomerList.Source = "Customers"
RsCustomerList.Open
%>
<HR>
<!-- Loop through Customers Table, adding 1 to the Counter variable each pass -->
<%
   Set MyRecordset = RSCustomerList.Clone
   Counter = 0
   Do Until MyRecordset.EOF
      Counter = Counter + 1
      MyRecordset.MoveNext
   Loop
%>
<!-- Display Results -->
<H3>There Are <%=Counter %> Records in the Customers Table</H3>
<BR><HR>
<H4>Location of DSN Datbase</H4>
<%' Show location of DSN data source
Response.Write(OBJdbConnection)
%>
<HR></Center></BODY></HTML>


Connect Property Example

This code shows how to set the Connect property at design time:

<OBJECT CLASSID="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33" ID="ADC1">
.
.
.
   <PARAM NAME="SQL" VALUE="Select * from Sales">
   <PARAM NAME="Connect" VALUE="DSN=pubs;UID=sa;PWD=;">
   <PARAM NAME="Server" VALUE="http://MyWebServer">
.
.
.
</OBJECT>

The following example shows how to set the Connect property at run time in VBScript code.

To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi3.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples </H2>
<HR>
<H3>Set Connect Property at Run Time</H3>
<!-- RDS.DataControl with no parameters set at design time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
   </OBJECT>
<Object classid="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE="Remote Data Service Connect Property at Run Time">
</OBJECT>
<HR>
<Input Size=70 Name="txtServer" Value="http://<%=Request.ServerVariables("SERVER_NAME")%>"><BR>
<Input Size=70 Name="txtConnect"><BR>
<Input Size=70 Name="txtSQL" Value="Select * from Employee">
<HR>
<INPUT TYPE=BUTTON NAME="Run" VALUE="Run"><BR>
<H4>To Fill Grid enter Connect String in middle text box<BR>
Try dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;</H4>
</Center>
<Script Language="VBScript">
<!--
' Set parameters of RDS.DataControl at Run Time
Sub Run_OnClick
   ADC.Server = txtServer.Value
   ADC.SQL = txtSQL.Value
   ADC.Connect = txtConnect.Value
   ADC.Refresh
End Sub
-->
</Script>


ConnectionString, ConnectionTimeout, and State Properties Example

This example demonstrates different ways of using the ConnectionString property to open a Connection object. It also uses the ConnectionTimeout property to set a connection timeout period, and the State property to check the state of the connections. The GetState function is required for this procedure to run.

Public Sub ConnectionStringX()

   Dim cnn1 As ADODB.Connection
   Dim cnn2 As ADODB.Connection
   Dim cnn3 As ADODB.Connection
   Dim cnn4 As ADODB.Connection

   ' Open a connection without using a Data Source Name (DSN).
   Set cnn1 = New ADODB.Connection
   cnn1.ConnectionString = "driver={SQL Server};" & _
      "server=bigsmile;uid=sa;pwd=pwd;database=pubs"
   cnn1.ConnectionTimeout = 30
   cnn1.Open

   ' Open a connection using a DSN and ODBC tags.
   Set cnn2 = New ADODB.Connection
   cnn2.ConnectionString = "DSN=Pubs;UID=sa;PWD=pwd;"
   cnn2.Open

   ' Open a connection using a DSN and OLE DB tags.
   Set cnn3 = New ADODB.Connection
   cnn3.ConnectionString = "Data Source=Pubs;User ID=sa;Password=pwd;"
   cnn3.Open

   ' Open a connection using a DSN and individual
   ' arguments instead of a connection string.
   Set cnn4 = New ADODB.Connection
   cnn4.Open "Pubs", "sa", "pwd"

   ' Display the state of the connections.
   MsgBox "cnn1 state: " & GetState(cnn1.State) & vbCr & _
      "cnn2 state: " & GetState(cnn2.State) & vbCr & _
      "cnn3 state: " & GetState(cnn3.State) & vbCr & _
      "cnn4 state: " & GetState(cnn4.State)

   cnn4.Close
   cnn3.Close
   cnn2.Close
   cnn1.Close

End Sub

Public Function GetState(intState As Integer) As String

   Select Case intState
      Case adStateClosed
         GetState = "adStateClosed"
      Case adStateOpen
         GetState = "adStateOpen"
   End Select

End Function


ConvertToString Method Example (VBScript)

Sub QueryRecordset_OnClick()
   Dim objADORs
      strServer = "http://<%=Request.ServerVariables("SERVER_NAME")%>"
      Set ADF = ADS1.CreateObject _
      ("RDSServer.DataFactory", strServer)
   Set objADORs = ADF.Query _
   (txtConnect.Value,txtQueryRecordset.Value)

ADF.ConvertToString(objADORs)

End Sub


Count Property Example

This example demonstrates the Count property with two collections in the Employee database. The property obtains the number of objects in each collection, and sets the upper limit for loops that enumerate these collections. Another way to enumerate these collections without using the Count property would be to use For Each...Next statements.

Public Sub CountX()

   Dim rstEmployees As ADODB.Recordset
   Dim strCnn As String
   Dim intloop As Integer

   ' Open recordset with data from Employee table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.Open "employee", strCnn, , , adCmdTable

   ' Print information about Fields collection.
   Debug.Print rstEmployees.Fields.Count & _
      " Fields in Employee"
   For intloop = 0 To rstEmployees.Fields.Count - 1
      Debug.Print "   " & rstEmployees.Fields(intloop).Name
   Next intloop

   ' Print information about Properties collection.
   Debug.Print rstEmployees.Properties.Count & _
      " Properties in Employee"
   For intloop = 0 To rstEmployees.Properties.Count - 1
      Debug.Print "   " & rstEmployees.Properties(intloop).Name
   Next intloop

   rstEmployees.Close

End Sub


CreateRecordset Method Example (VBScript)

This code example creates an ADODB.Recordset on the server side. It has two columns with four rows each.

Sub CreateARecordSet
   Dim ColInfo(1), c0(3), c1(3)

   c0(0) = "Name"         ' Column name.
   c0(1) = CInt(129)      ' Column type (129 = adChar).
   c0(2) = CInt(40)      ' Column size.
   c0(3) = False         ' Is the column nullable?

   c1(0) = "Age"         ' Column name.
   c1(1) = CInt(3)      ' Column type (3 = adInteger).
   c1(2) = CInt(-1)      ' Column size.
   c1(3) = True         ' Is the column nullable?

   ' Add the columns to the recordset definition.
   ColInfo(0) = c0
   ColInfo(1) = c1

   ADC1.SourceRecordset = ADF1.CreateRecordset(ColInfo)
End Sub


CursorType, LockType, and EditMode Properties Example

This example demonstrates setting the CursorType and LockType properties before opening a Recordset. It also shows the value of the EditMode property under various conditions. The EditModeOutput function is required for this procedure to run.

Public Sub EditModeX()

   Dim cnn1 As ADODB.Connection
   Dim rstEmployees As ADODB.Recordset
   Dim strCnn As String

   ' Open recordset with data from Employee table.
   Set cnn1 = New ADODB.Connection
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn

   Set rstEmployees = New ADODB.Recordset
   Set rstEmployees.ActiveConnection = cnn1
   rstEmployees.CursorType = adOpenKeyset
   rstEmployees.LockType = adLockBatchOptimistic
   rstEmployees.Open "employee", , , , adCmdTable

   ' Show the EditMode property under different editing
   ' states.
   rstEmployees.AddNew
   rstEmployees!emp_id = "T-T55555M"
   rstEmployees!fname = "temp_fname"
   rstEmployees!lname = "temp_lname"
   EditModeOutput "After AddNew:", rstEmployees.EditMode
   rstEmployees.UpdateBatch
   EditModeOutput "After UpdateBatch:", rstEmployees.EditMode
   rstEmployees!fname = "test"
   EditModeOutput "After Edit:", rstEmployees.EditMode
   rstEmployees.Close

   ' Delete new record because this is a demonstration.
   cnn1.Execute "DELETE FROM employee WHERE emp_id = 'T-T55555M'"

End Sub

Public Function EditModeOutput(strTemp As String, _
   intEditMode As Integer)

   ' Print report based on the value of the EditMode
   ' property.
   Debug.Print strTemp
   Debug.Print "  EditMode = ";

   Select Case intEditMode
      Case adEditNone
         Debug.Print "adEditNone"
      Case adEditInProgress
         Debug.Print "adEditInProgress"
      Case adEditAdd
         Debug.Print "adEditAdd"
   End Select

End Function


Delete Method Example

This example uses the Delete method to remove a specified record from a Recordset.

Public Sub DeleteX()

   Dim rstRoySched As ADODB.Recordset
   Dim strCnn As String
   Dim strMsg As String
   Dim strTitleID As String
   Dim intLoRange As Integer
   Dim intHiRange As Integer
   Dim intRoyalty As Integer

   ' Open RoySched table.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstRoySched = New ADODB.Recordset
   rstRoySched.CursorLocation = adUseClient
   rstRoySched.CursorType = adOpenStatic
   rstRoySched.LockType = adLockBatchOptimistic
   rstRoySched.Open "SELECT * FROM roysched " & _
      "WHERE royalty = 20", strCnn, , , adCmdText

   ' Prompt for a record to delete.
   strMsg = "Before delete there are " & _
      rstRoySched.RecordCount & _
      " titles with 20 percent royalty:" & vbCr & vbCr
   Do While Not rstRoySched.EOF
      strMsg = strMsg & rstRoySched!title_id & vbCr
      rstRoySched.MoveNext
   Loop
   strMsg = strMsg & vbCr & vbCr & _
      "Enter the ID of a record to delete:"
   strTitleID = UCase(InputBox(strMsg))

   ' Move to the record and save data so it can be restored.
   rstRoySched.Filter = "title_id = '" & strTitleID & "'"
   intLoRange = rstRoySched!lorange
   intHiRange = rstRoySched!hirange
   intRoyalty = rstRoySched!royalty

   ' Delete the record.
   rstRoySched.Delete
   rstRoySched.UpdateBatch

   ' Show the results.
   rstRoySched.Filter = adFilterNone
   rstRoySched.Requery
   strMsg = ""
   strMsg = "After delete there are " & _
      rstRoySched.RecordCount & _
      " titles with 20 percent royalty:" & vbCr & vbCr
   Do While Not rstRoySched.EOF
      strMsg = strMsg & rstRoySched!title_id & vbCr
      rstRoySched.MoveNext
   Loop
   MsgBox strMsg

   ' Restore the data because this is a demonstration.
   rstRoySched.AddNew
   rstRoySched!title_id = strTitleID
   rstRoySched!lorange = intLoRange
   rstRoySched!hirange = intHiRange
   rstRoySched!royalty = intRoyalty
   rstRoySched.UpdateBatch

   rstRoySched.Close

End Sub

VBScript Version

Here is the same example written in VBScript to be used in an Active Server Page (ASP). To view this fully functional example, you need to create a system Data Source Name (DSN) called AdvWorks using the data source AdvWorks.mdb installed with IIS and located at C:\InetPub\ASPSamp\AdvWorks. This is a Microsoft Access database file. Use Find to locate the file Adovbs.inc and place it in the directory you plan to use. Cut and paste the following code to Notepad or another text editor and save it as Delete.asp. You can view the result in any client browser.

To exercise the example, try using the AddNew example first to add some records. Then you can try to delete them. View the result in any client browser.

<!-- #Include file="ADOVBS.INC" -->
<% Language = VBScript %>

<HTML>

<HEAD><TITLE>ADO Delete Method</TITLE>
</HEAD><BODY>
<FONT FACE="MS SANS SERIF" SIZE=2>
<Center><H3>ADO Delete Method</H3>

<!--- ADO Connection Object used to create recordset-->
<%
'Create and Open Connection Object
Set OBJdbConnection = Server.CreateObject("ADODB.Connection")
OBJdbConnection.Open "AdvWorks"
'Create and Open Recordset Object
Set RsCustomerList = Server.CreateObject("ADODB.Recordset")
RsCustomerList.ActiveConnection = OBJdbConnection
RsCustomerList.CursorType = adOpenKeyset
RsCustomerList.LockType = adLockOptimistic
RsCustomerList.Source = "Customers"
RsCustomerList.Open
%>
<!-- Move to designated record and delete it -->
<%

If Not IsEmpty(Request.Form("WhichRecord")) Then
   'Get value to move from Form Post method
   Moves = Request.Form("WhichRecord")

   RsCustomerList.Move CInt(Moves)
   If Not RsCustomerList.EOF or RsCustomerList.BOF Then
      RsCustomerList.Delete 1
      RsCustomerList.MoveFirst

   Else
      Response.Write "Not a Valid Record Number"
      RsCustomerList.MoveFirst
   End If
End If

%>
<!-- BEGIN column header row for Customer Table-->

<TABLE COLSPAN=8 CELLPADDING=5 BORDER=0><TR>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Company Name</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Contact Name</FONT>
</TD>
<TD ALIGN=CENTER WIDTH=150 BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Phone Number</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>City</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>State/Province</FONT>
</TD></TR>

<!--Display ADO Data from Customer Table Loop through Recordset adding
One Row to HTML Table each pass-->
<% Do While Not RsCustomerList.EOF %>
  <TR><TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RSCustomerList("CompanyName")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("ContactLastName") & ", " %>
  <%= RScustomerList("ContactFirstName") %>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("PhoneNumber")%>
 </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("City")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("StateOrProvince")%>
  </FONT></TD>
  </TR>
<!-Next Row = Record Loop and add to html table-->
<%
RScustomerList.MoveNext
Loop
%>
</Table></Center></FONT>
<!-- Do Client side Input Data Validation Move to named record and Delete it -->

<Center>
<H4>Clicking Button Will Remove Designated Record</H4>
<H5>There are <%=RsCustomerList.RecordCount - 1%> Records in this Set</H5>
<Form Method = Post Action = "Delete.asp" Name = Form>
<Input Type = Text Name = "WhichRecord" Size = 3></Form>
<Input Type = Button Name = cmdDelete Value = "Delete Record"></Center>

</BODY>

<Script Language = "VBScript">

Sub cmdDelete_OnClick
If IsNumeric(Document.Form.WhichRecord.Value) Then
   Document.Form.WhichRecord.Value = CInt(Document.Form.WhichRecord.Value)
Dim Response
   Response = MsgBox("Are You Sure About Deleting This Record?", vbYesNo,  "ADO-ASP

Example")

   If Response = vbYes Then

   Document.Form.Submit

   End If
Else
   MsgBox "You Must Enter a Valid Record Number",,"ADO-ASP Example"
End If
End Sub

</Script>
</HTML>


Description, NativeError, Number, Source, and SQLState Properties Example

This example triggers an error, traps it, and displays the Description, HelpContext, HelpFile, NativeError, Number, Source, and SQLState properties of the resulting Error object.

Public Sub DescriptionX()

   Dim cnn1 As ADODB.Connection
   Dim errLoop As ADODB.Error
   Dim strError As String

   On Error GoTo ErrorHandler

   ' Intentionally trigger an error.
   Set cnn1 = New ADODB.Connection
   cnn1.Open "nothing"

   Exit Sub

ErrorHandler:

   ' Enumerate Errors collection and display
   ' properties of each Error object.
   For Each errLoop In cnn1.Errors
      strError = "Error #" & errLoop.Number & vbCr & _
         "   " & errLoop.Description & vbCr & _
         "   (Source: " & errLoop.Source & ")" & vbCr & _
         "   (SQL State: " & errLoop.SQLState & ")" & vbCr & _
         "   (NativeError: " & errLoop.NativeError & ")" & vbCr
      If errLoop.HelpFile = "" Then
         strError = strError & _
            "   No Help file available" & _
            vbCr & vbCr
      Else
         strError = strError & _
            "   (HelpFile: " & errLoop.HelpFile & ")" & vbCr & _
            "   (HelpContext: " & errLoop.HelpContext & ")" & _
            vbCr & vbCr
      End If

   Debug.Print strError
   Next

   Resume Next

End Sub


Execute, Requery, and Clear Methods Example

This example demonstrates the Execute method when run from both a Command object and a Connection object. It also uses the Requery method to retrieve current data in a recordset, and the Clear method to clear the contents of the Errors collection. The ExecuteCommand and PrintOutput procedures are required for this procedure to run.

Public Sub ExecuteX()

   Dim strSQLChange As String
   Dim strSQLRestore As String
   Dim strCnn As String
   Dim cnn1 As ADODB.Connection
   Dim cmdChange As ADODB.Command
   Dim rstTitles As ADODB.Recordset
   Dim errLoop As ADODB.Error

   ' Define two SQL statements to execute as command text.
   strSQLChange = "UPDATE Titles SET Type = " & _
      "'self_help' WHERE Type = 'psychology'"
   strSQLRestore = "UPDATE Titles SET Type = " & _
      "'psychology' WHERE Type = 'self_help'"

   ' Open connection.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set cnn1 = New ADODB.Connection
   cnn1.Open strCnn

   ' Create command object.
   Set cmdChange = New ADODB.Command
   Set cmdChange.ActiveConnection = cnn1
   cmdChange.CommandText = strSQLChange

   ' Open titles table.
   Set rstTitles = New ADODB.Recordset
   rstTitles.Open "titles", cnn1, , , adCmdTable

   ' Print report of original data.
   Debug.Print _
      "Data in Titles table before executing the query"
   PrintOutput rstTitles

   ' Clear extraneous errors from the Errors collection.
   cnn1.Errors.Clear

   ' Call the ExecuteCommand subroutine to execute cmdChange command.
   ExecuteCommand cmdChange, rstTitles

   ' Print report of new data.
   Debug.Print _
      "Data in Titles table after executing the query"
   PrintOutput rstTitles

   ' Use the Connection object's execute method to
   ' execute SQL statement to restore data. Trap for
   ' errors, checking the Errors collection if necessary.
   On Error GoTo Err_Execute
   cnn1.Execute strSQLRestore, , adExecuteNoRecords
   On Error GoTo 0

   ' Retrieve the current data by requerying the recordset.
   rstTitles.Requery

   ' Print report of restored data.
   Debug.Print "Data after executing the query " & _
      "to restore the original information"
   PrintOutput rstTitles

   rstTitles.Close
   cnn1.Close

   Exit Sub

Err_Execute:

   ' Notify user of any errors that result from
   ' executing the query.
   If Errors.Count > 0 Then
      For Each errLoop In Errors
         MsgBox "Error number: " & errLoop.Number & vbCr & _
            errLoop.Description
      Next errLoop
   End If

   Resume Next

End Sub

Public Sub ExecuteCommand(cmdTemp As ADODB.Command, _
   rstTemp As ADODB.Recordset)

   Dim errLoop As Error

   ' Run the specified Command object. Trap for
   ' errors, checking the Errors collection if necessary.
   On Error GoTo Err_Execute
   cmdTemp.Execute
   On Error GoTo 0

   ' Retrieve the current data by requerying the recordset.
   rstTemp.Requery

   Exit Sub

Err_Execute:

   ' Notify user of any errors that result from
   ' executing the query.
   If Errors.Count > 0 Then
      For Each errLoop In Errors
         MsgBox "Error number: " & errLoop.Number & vbCr & _
            errLoop.Description
      Next errLoop
   End If

   Resume Next

End Sub

Public Sub PrintOutput(rstTemp As ADODB.Recordset)

   ' Enumerate Recordset.
   Do While Not rstTemp.EOF
      Debug.Print "  " & rstTemp!Title & _
         ", " & rstTemp!Type
      rstTemp.MoveNext
   Loop

End Sub

VBScript Version

Here is the same example written in VBScript to be used in an Active Server Page (ASP). To view this fully functional example, you need to create a system Data Source Name (DSN) called AdvWorks using the data source AdvWorks.mdb installed with IIS and located at C:\InetPub\ASPSamp\AdvWorks. This is a Microsoft Access database file. Use Find to locate the file Adovbs.inc and place it in the directory you plan to use. Cut and paste the following code to Notepad or another text editor and save it as Execute.asp. You can view the result in any client browser.

<!-- #Include file="ADOVBS.INC" -->
<HTML><HEAD>
<TITLE>ADO Execute Method</TITLE></HEAD>

<BODY>
<FONT FACE="MS SANS SERIF" SIZE=2>
<Center><H3>ADO Execute Method</H3><H4>Recordset Retrieved Using Connection Object</H4>
<TABLE WIDTH=600 BORDER=0>
<TD VALIGN=TOP ALIGN=LEFT COLSPAN=3><FONT SIZE=2>

<!--- Recordsets retrieved using Execute method of Connection and Command Objects-->
<%
Set OBJdbConnection = Server.CreateObject("ADODB.Connection")
OBJdbConnection.Open "AdvWorks"
SQLQuery = "SELECT * FROM Customers"
'First Recordset RSCustomerList
Set RSCustomerList = OBJdbConnection.Execute(SQLQuery)

Set OBJdbCommand = Server.CreateObject("ADODB.Command")
OBJdbCommand.ActiveConnection = OBJdbConnection
SQLQuery2 = "SELECT * From Products"
OBJdbCommand.CommandText = SQLQuery2
Set RsProductList = OBJdbCommand.Execute

%>
<TABLE COLSPAN=8 CELLPADDING=5 BORDER=0>

<!-- BEGIN column header row for Customer Table-->

<TR><TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Company Name</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Contact Name</FONT>
</TD>
<TD ALIGN=CENTER WIDTH=150 BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>E-mail address</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>City</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>State/Province</FONT>
</TD></TR>

<!--Display ADO Data from Customer Table-->
<% Do While Not RScustomerList.EOF %>
  <TR>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RSCustomerList("CompanyName")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("ContactLastName") & ", " %>
  <%= RScustomerList("ContactFirstName") %>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>

  <%= RScustomerList("ContactLastName")%>
 </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("City")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("StateOrProvince")%>
  </FONT></TD>
  </TR>
<!-Next Row = Record Loop and add to html table-->
<%
RScustomerList.MoveNext
Loop
RScustomerList.Close

%>

</TABLE><HR>
<H4>Recordset Retrieved Using Command Object</H4>
<TABLE COLSPAN=8 CELLPADDING=5 BORDER=0>

<!-- BEGIN column header row for Product List Table-->

<TR><TD ALIGN=CENTER BGCOLOR="#800000">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Product Type</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#800000">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Product Name</FONT>
</TD>
<TD ALIGN=CENTER WIDTH=350 BGCOLOR="#800000">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Product Description</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#800000">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Unit Price</FONT>
</TD></TR>

<!-- Display ADO Data Product List-->
<% Do While Not RsProductList.EOF %>
  <TR>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RsProductList("ProductType")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RsProductList("ProductName")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
   <%= RsProductList("ProductDescription")%>
 </FONT></TD>

  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RsProductList("UnitPrice")%>
  </FONT></TD>

<!--  Next Row = Record -->
<%
RsProductList.MoveNext
Loop
'Remove objects from memory to free resources
RsProductList.Close
OBJdbConnection.Close
Set ObJdbCommand = Nothing
Set RsProductList = Nothing
Set OBJdbConnection = Nothing
%>
</TABLE></FONT></Center></BODY></HTML>


ExecuteOptions and FetchOptions Properties Example

The following code shows how to set the ExecuteOptions and FetchOptions properties at design time. If left unset, ExecuteOptions defaults to adcExecSync. This setting indicates that when the ADC.Refresh method is called it will be executed on the current calling thread—that is, synchronously.

<OBJECT CLASSID="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33" ID="ADC1">
.
.
.
<PARAM NAME="SQL" VALUE="Select * from Sales">
<PARAM NAME="Connect" VALUE="DSN=pubs;UID=sa;PWD=;">
<PARAM NAME="Server" VALUE="http://MyWebServer">
<PARAM NAME="ExecuteOptions"VALUE="1">
<PARAM NAME="FetchOptions"VALUE="3">

.
.
</OBJECT>

The following example shows how to set the ExecuteOptions and FetchOptions properties at run time in VBScript code. See the Refresh method for a working example of these properties.

<Script Language="VBScript">
<!--
Sub ExecuteHow
' Execute next refresh of Recordset asynchronously to the calling thread
ADC1.ExecuteOptions = 1
ADC1.FetchOptions = 3
ADC.Refresh
End Sub
-->
</Script>


Filter and RecordCount Properties Example

This example uses the Filter property to open a new Recordset based on a specified condition applied to an existing Recordset. It uses the RecordCount property to show the number of records in the two Recordsets. The FilterField function is required for this procedure to run.

Public Sub FilterX()

   Dim rstPublishers As ADODB.Recordset
   Dim rstPublishersCountry As ADODB.Recordset
   Dim strCnn As String
   Dim intPublisherCount As Integer
   Dim strCountry As String
   Dim strMessage As String

   ' Open recordset with data from Publishers table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstPublishers = New ADODB.Recordset
   rstPublishers.CursorType = adOpenStatic
   rstPublishers.Open "publishers", strCnn, , , adCmdTable

   ' Populate the Recordset.
   intPublisherCount = rstPublishers.RecordCount

   ' Get user input.
   strCountry = Trim(InputBox( _
      "Enter a country to filter on:"))

   If strCountry <> "" Then
      ' Open a filtered Recordset object.
      Set rstPublishersCountry = _
         FilterField(rstPublishers, "Country", strCountry)

      If rstPublishersCountry.RecordCount = 0 Then
         MsgBox "No publishers from that country."
      Else
         ' Print number of records for the original
         ' Recordset object and the filtered Recordset
         ' object.
         strMessage = "Orders in original recordset: " & _
            vbCr & intPublisherCount & vbCr & _
            "Orders in filtered recordset (Country = '" & _
            strCountry & "'): " & vbCr & _
            rstPublishersCountry.RecordCount
         MsgBox strMessage
      End If
      rstPublishersCountry.Close

   End If

End Sub

Public Function FilterField(rstTemp As ADODB.Recordset, _
   strField As String, strFilter As String) As ADODB.Recordset

   ' Set a filter on the specified Recordset object and then
   ' open a new Recordset object.
   rstTemp.Filter = strField & " = '" & strFilter & "'"
   Set FilterField = rstTemp

End Function

Note When you know the data you want to select, it's usually more efficient to open a Recordset with an SQL statement. This example shows how you can create just one Recordset and obtain records from a particular country.

Public Sub FilterX2()

   Dim rstPublishers As ADODB.Recordset
   Dim strCnn As String

   ' Open recordset with data from Publishers table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstPublishers = New ADODB.Recordset
   rstPublishers.CursorType = adOpenStatic
   rstPublishers.Open "SELECT * FROM publishers " & _
      "WHERE Country = 'USA'", strCnn, , , adCmdText

   ' Print current data in recordset.
   rstPublishers.MoveFirst
   Do While Not rstPublishers.EOF
      Debug.Print rstPublishers!pub_name & ", " & _
         rstPublishers!country
      rstPublishers.MoveNext
   Loop

   rstPublishers.Close

End Sub


FilterColumn, FilterCriterion, FilterValue, SortColumn, and SortDirection Properties and Reset Method Example

The following code shows how to set the RDS.DataControl Server parameter at design time and bind it to a data-aware control using an ODBC data source called Pubs. Pubs ships with SQL Server 6.5. To try the example you will need rich text controls named txtSortcolumn, txtSortdirection, txtFiltercolumn, txtCriterion, and txtFilterValue, and an HTML Form Input Button named SortFilter.

<OBJECT CLASSID="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
ID=ADC HEIGHT=10 WIDTH=10>
<PARAM NAME="SQL" VALUE="Select * from Sales ">
<PARAM NAME="SERVER" VALUE="http://MyWebServer">
<PARAM NAME="CONNECT" VALUE="dsn=pubs;UID=sa;PWD=;">
</OBJECT>

<!-- Sheridan Grid -->
<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://MyWebServer
/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="BackColor"   VALUE="-2147483643">
   <PARAM NAME="BackColorOdd"  VALUE="-2147483643">
   <PARAM NAME="ForeColorEven" VALUE="0">
</OBJECT>

<Script Language="VBScript">
<!--
Sub SortFilter_OnClick

   ' Set the values. txtSortcolumn is a rich text box
   ' control. The value of SortColumn will be the text
   ' value of what the user specifies in the
   ' txtSortcolumn box.
   If(txtSortcolumn.text <> "") then
      ADC.SortColumn = txtSortcolumn.text
   End If

   ' txtSortdirection is a rich text box
   ' control. The value of SortDirection will be the
   ' text value of what the user specifies in the
   ' txtSortdirection box.
   Select Case UCASE(txtSortDirection.text)
   Case "TRUE"
      ADC.SortDirection = TRUE
   Case "FALSE"
      ADC.SortDirection = FALSE
   Case Else
      MsgBox "Only true or false are accepted for sort direction"
   End Select

   ' txtFiltercolumn is a rich text box
   ' control. The value of FilterColumn will be the
   ' text value of what the user specifies in the
   ' txtFiltercolumn box.
   If (txtFiltercolumn.text <> "") Then
      ADC.FilterColumn = txtFiltercolumn.text
   End If

   ' txtCriterion is a rich text box
   ' control. The value of FilterCriterion will be the
   ' text value of what the user specifies in the
   ' txtCriterion box.
   If (txtCriterion.text <> "") Then
      ADC.FilterCriterion = txtCriterion.text
   End If

   ' txtFilterValue is a rich text box
   ' control. The value of FilterValue will be the
   ' text value of what the user specifies in the
   ' txtFilterValue box.
   If (txtFilterValue.text <> "") Then
      ADC.FilterValue = txtFilterValue.text
   End If

   ' Execute the sort and filter on a client-side
   ' Recordset based on the specified sort and filter
   ' properties. Calling Reset refreshes the result set
   ' that is displayed in the data-bound controls to
   ' display the filtered, sorted recordset.
   ADC.Reset

End Sub
-->
</Script>


GetRows Method Example

This example uses the GetRows method to retrieve a specified number of rows from a Recordset and to fill an array with the resulting data. The GetRows method will return fewer than the desired number of rows in two cases: either if EOF has been reached, or if GetRows tried to retrieve a record that was deleted by another user. The function returns False only if the second case occurs. The GetRowsOK function is required for this procedure to run.

Public Sub GetRowsX()

   Dim rstEmployees As ADODB.Recordset
   Dim strCnn As String
   Dim strMessage As String
   Dim intRows As Integer
   Dim avarRecords As Variant
   Dim intRecord As Integer

   ' Open recordset with names and hire dates from employee table.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.Open "SELECT fName, lName, hire_date " & _
      "FROM Employee ORDER BY lName", strCnn, , , adCmdText

   Do While True
      ' Get user input for number of rows.
      strMessage = "Enter number of rows to retrieve."
      intRows = Val(InputBox(strMessage))

      If intRows <= 0 Then Exit Do

      ' If GetRowsOK is successful, print the results,
      ' noting if the end of the file was reached.
      If GetRowsOK(rstEmployees, intRows, _
            avarRecords) Then
         If intRows > UBound(avarRecords, 2) + 1 Then
            Debug.Print "(Not enough records in " & _
               "Recordset to retrieve " & intRows & _
               " rows.)"
         End If
         Debug.Print UBound(avarRecords, 2) + 1 & _
            " records found."

         ' Print the retrieved data.
         For intRecord = 0 To UBound(avarRecords, 2)
            Debug.Print "  " & _
               avarRecords(0, intRecord) & " " & _
               avarRecords(1, intRecord) & ", " & _
               avarRecords(2, intRecord)
         Next intRecord
      Else
         ' Assuming the GetRows error was due to data
         ' changes by another user, use Requery to
         ' refresh the Recordset and start over.
         If MsgBox("GetRows failed--retry?", _
               vbYesNo) = vbYes Then
            rstEmployees.Requery
         Else
            Debug.Print "GetRows failed!"
            Exit Do
         End If
      End If

      ' Because using GetRows leaves the current
      ' record pointer at the last record accessed,
      ' move the pointer back to the beginning of the
      ' Recordset before looping back for another search.
      rstEmployees.MoveFirst
   Loop

   rstEmployees.Close

End Sub

Public Function GetRowsOK(rstTemp As ADODB.Recordset, _
   intNumber As Integer, avarData As Variant) As Boolean

   ' Store results of GetRows method in array.
   avarData = rstTemp.GetRows(intNumber)
   ' Return False only if fewer than the desired
   ' number of rows were returned, but not because the
   ' end of the Recordset was reached.
   If intNumber > UBound(avarData, 2) + 1 And _
         Not rstTemp.EOF Then
      GetRowsOK = False
   Else
      GetRowsOK = True
   End If

End Function


IsolationLevel and Mode Properties Example

This example uses the Mode property to open an exclusive connection, and the IsolationLevel property to open a transaction that is conducted in isolation of other transactions.

Public Sub IsolationLevelX()

   Dim cnn1 As ADODB.Connection
   Dim rstTitles As ADODB.Recordset
   Dim strCnn As String

   ' Assign connection string to variable.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "

   ' Open connection and titles table.
   Set cnn1 = New ADODB.Connection
   cnn1.Mode = adModeShareExclusive
   cnn1.IsolationLevel = adXactIsolated
   cnn1.Open strCnn

   Set rstTitles = New ADODB.Recordset
   rstTitles.CursorType = adOpenDynamic
   rstTitles.LockType = adLockPessimistic
   rstTitles.Open "titles", cnn1, , , adCmdTable

   cnn1.BeginTrans

   ' Display connection mode.
   If cnn1.Mode = adModeShareExclusive Then
      MsgBox "Connection mode is exclusive."
   Else
      MsgBox "Connection mode is not exclusive."
   End If

   ' Display isolation level.
   If cnn1.IsolationLevel = adXactIsolated Then
      MsgBox "Transaction is isolated."
   Else
      MsgBox "Transaction is not isolated."
   End If

   ' Change the type of psychology titles.
   Do Until rstTitles.EOF
      If Trim(rstTitles!Type) = "psychology" Then
         rstTitles!Type = "self_help"
         rstTitles.Update
      End If
      rstTitles.MoveNext
   Loop

   ' Print current data in recordset.
   rstTitles.Requery
   Do While Not rstTitles.EOF
      Debug.Print rstTitles!Title & " - " & rstTitles!Type
      rstTitles.MoveNext
   Loop

   ' Restore original data.
   cnn1.RollbackTrans
   rstTitles.Close

   cnn1.Close

End Sub


MarshalOptions Property Example

This example uses the MarshalOptions property to specify what rows are sent back to the server—All Rows or only Modified Rows.

Public Sub MarshalOptionsX()

   Dim rstEmployees As ADODB.Recordset
   Dim strCnn As String
   Dim strOldFirst As String
   Dim strOldLast As String
   Dim strMessage As String
   Dim strMarshalAll As String
   Dim strMarshalModified As String

   ' Open recordset with names from Employee table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.CursorType = adOpenKeyset
   rstEmployees.LockType = adLockOptimistic
   rstEmployees.CursorLocation = adUseClient
   rstEmployees.Open "SELECT fname, lname " & _
      "FROM Employee ORDER BY lname", strCnn, , , adCmdText

   ' Store original data.
   strOldFirst = rstEmployees!fname
   strOldLast = rstEmployees!lname

   ' Change data in edit buffer.
   rstEmployees!fname = "Linda"
   rstEmployees!lname = "Kobara"

   ' Show contents of buffer and get user input.
   strMessage = "Edit in progress:" & vbCr & _
      " Original data = " & strOldFirst & " " & _
      strOldLast & vbCr & " Data in buffer = " & _
      rstEmployees!fname & " " & rstEmployees!lname & vbCr & vbCr & _
      "Use Update to replace the original data with " & _
      "the buffered data in the Recordset?"
   strMarshalAll = "Would you like to send all the rows " & _
               "in the recordset back to the server?"
   strMarshalModified = "Would you like to send only " & _
               "modified rows back to the server?"

   If MsgBox(strMessage, vbYesNo) = vbYes Then
      If MsgBox(strMarshalAll, vbYesNo) = vbYes Then
         rstEmployees.MarshalOptions = adMarshalAll
         rstEmployees.Update
      ElseIf MsgBox(strMarshalModified, vbYesNo) = vbYes Then
         rstEmployees.MarshalOptions = adMarshalModifiedOnly
         rstEmployees.Update
      End If
   End If

   ' Show the resulting data.
   MsgBox "Data in recordset = " & rstEmployees!fname & " " & _
      rstEmployees!lname

   ' Restore original data because this is a demonstration.
   If Not (strOldFirst = rstEmployees!fname And _
         strOldLast = rstEmployees!lname) Then
      rstEmployees!fname = strOldFirst
      rstEmployees!lname = strOldLast
      rstEmployees.Update
   End If

   rstEmployees.Close

End Sub


MaxRecords Property Example

This example uses the MaxRecords property to open a Recordset containing the 10 most expensive titles in the Titles table.

Public Sub MaxRecordsX()

   Dim rstTemp As ADODB.Recordset
   Dim strCnn As String

   ' Open recordset containing the 10 most expensive
   ' titles in the Titles table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstTemp = New ADODB.Recordset
   rstTemp.MaxRecords = 10
   rstTemp.Open "SELECT Title, Price FROM Titles " & _
      "ORDER BY Price DESC", strCnn, , , adCmdText

   ' Display the contents of the recordset.
   Debug.Print "Top Ten Titles by Price:"

   Do While Not rstTemp.EOF
      Debug.Print "  " & rstTemp!Title & " - " & rstTemp!Price
      rstTemp.MoveNext
   Loop
   rstTemp.Close

End Sub


Move Method Example

This example uses the Move method to position the record pointer based on user input.

Public Sub MoveX()

   Dim rstAuthors As ADODB.Recordset
   Dim strCnn As String
   Dim varBookmark As Variant
   Dim strCommand As String
   Dim lngMove As Long

   ' Open recordset from Authors table.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstAuthors = New ADODB.Recordset
   rstAuthors.CursorType = adOpenStatic
   ' Use client cursor to allow use of
   ' AbsolutePosition property.
   rstAuthors.CursorLocation = adUseClient
   rstAuthors.Open "SELECT au_id, au_fname, au_lname, city, state " & _
      "FROM Authors ORDER BY au_lname", strCnn, , , adCmdText

   rstAuthors.MoveFirst

   Do While True
      ' Display information about current record and
      ' ask how many records to move.

      strCommand = InputBox( _
         "Record " & rstAuthors.AbsolutePosition & _
         " of " & rstAuthors.RecordCount & vbCr & _
         "Author: " & rstAuthors!au_fname & _
         " " & rstAuthors!au_lname & vbCr & _
         "Location: " & rstAuthors!City & _
         ", " & rstAuthors!State & vbCr & vbCr & _
         "Enter number of records to Move " & _
         "(positive or negative).")

      If strCommand = "" Then Exit Do

      ' Store bookmark in case the Move goes too far
      ' forward or backward.
      varBookmark = rstAuthors.Bookmark

      ' Move method requires parameter of data type Long.
      lngMove = CLng(strCommand)
      rstAuthors.Move lngMove

      ' Trap for BOF or EOF.
      If rstAuthors.BOF Then
         MsgBox "Too far backward! " & _
            "Returning to current record."
         rstAuthors.Bookmark = varBookmark
      End If
      If rstAuthors.EOF Then
         MsgBox "Too far forward! " & _
            "Returning to current record."
         rstAuthors.Bookmark = varBookmark
      End If
   Loop
   rstAuthors.Close

End Sub

VBScript Version

Here is the same example written in VBScript to be used in an Active Server Page (ASP). To view this fully functional example, you need to create a system Data Source Name (DSN) called AdvWorks using the data source AdvWorks.mdb installed with IIS and located at C:\InetPub\ASPSamp\AdvWorks. This is a Microsoft Access database file. Use Find to locate the file Adovbs.inc and place it in the directory you plan to use. Cut and paste the following code to Notepad or another text editor and save it as Move.asp. You can view the result in any client browser.

Try entering a letter or non integer to see the error handling work.

<!-- #Include file="ADOVBS.INC" -->
<% Language = VBScript %>
<HTML><HEAD>
<TITLE>ADO Move Methods</TITLE></HEAD>
<BODY>
<FONT FACE="MS SANS SERIF" SIZE=2>
<Center>
<H3>ADO Move Methods</H3>

<%
 'Create and Open Connection Object
Set OBJdbConnection = Server.CreateObject("ADODB.Connection")
OBJdbConnection.Open "AdvWorks"
'Create and Open Recordset Object
Set RsCustomerList = Server.CreateObject("ADODB.Recordset")
RsCustomerList.ActiveConnection = OBJdbConnection
RsCustomerList.CursorType = adOpenKeyset
RsCustomerList.LockType = adLockOptimistic
RsCustomerList.Source = "Customers"

RsCustomerList.Open

'Check number of user moves this session
'Increment by amount in Form
Session("Clicks") = Session("Clicks") + Request.Form("MoveAmount")
Clicks = Session("Clicks")
'Move to last known recordset position plus amount passed
'by Form Post method
RsCustomerList.Move CInt(Clicks)

'Error Handling
   If RsCustomerList.EOF Then
         Session("Clicks") = RsCustomerList.RecordCount
         Response.Write "This is the Last Record"
         RsCustomerList.MoveLast
      Else If RsCustomerList.BOF Then
         Session("Clicks") = 1
         RsCustomerList.MoveFirst
         Response.Write "This is the First Record"
      End If
   End If

%>

<H3>Current Record Number is <BR>
<% If Session("Clicks") = 0 Then
Session("Clicks") = 1
End If
Response.Write(Session("Clicks") )%> of <%=RsCustomerList.RecordCount%></H3>
<HR>

<Center><TABLE COLSPAN=8 CELLPADDING=5 BORDER=0>

<!-- BEGIN column header row for Customer Table-->

<TR>

<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Company Name</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Contact Name</FONT>
</TD>
<TD ALIGN=CENTER WIDTH=150 BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Phone Number</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>City</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>State/Province</FONT>
</TD>

</TR>

<!--Display ADO Data from Customer Table-->

  <TR>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RSCustomerList("CompanyName")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("ContactLastName") & ", " %>
  <%= RScustomerList("ContactFirstName") %>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>

  <%= RScustomerList("PhoneNumber")%>
 </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("City")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("StateOrProvince")%>
  </FONT></TD>
  </TR> </Table></FONT>

<HR>
<Input Type = Button Name = cmdDown  Value = "<  ">
<Input Type = Button Name = cmdUp Value = " >">
<H5>Click Direction Arrows for Previous or Next Record
<BR> Click Move Amount to use Move Method
Enter Number of Records to Move + or - </H5>

<Table>

<Form Method = Post Action="Move.asp" Name=Form>

<TR><TD><Input Type="Button" Name = Move Value="Move Amount "></TD><TD></TD><TD>
<Input Type="Text" Size="4" Name="MoveAmount" Value = 0></TD><TR>
</Form></Table></Center>

</BODY>

<Script Language = "VBScript">

Sub Move_OnClick
' Make sure move value entered is an integer
If IsNumeric(Document.Form.MoveAmount.Value)Then
   Document.Form.MoveAmount.Value = CInt(Document.Form.MoveAmount.Value)
   Document.Form.Submit
Else
   MsgBox "You Must Enter a Number", ,"ADO-ASP Example"
   Document.Form.MoveAmount.Value = 0
End If

End Sub

Sub cmdDown_OnClick

Document.Form.MoveAmount.Value = -1
Document.Form.Submit

End Sub

Sub cmdUp_OnClick

Document.Form.MoveAmount.Value = 1
Document.Form.Submit

End Sub

</Script>
</HTML>


MoveFirst, MoveLast, MoveNext, and MovePrevious Methods Example

This example uses the MoveFirst, MoveLast, MoveNext, and MovePrevious methods to move the record pointer of a Recordset based on the supplied command. The MoveAny procedure is required for this procedure to run.

Public Sub MoveFirstX()

   Dim rstAuthors As ADODB.Recordset
   Dim strCnn As String
   Dim strMessage As String
   Dim intCommand As Integer

   ' Open recordset from Authors table.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstAuthors = New ADODB.Recordset
   rstAuthors.CursorType = adOpenStatic
   ' Use client cursor to enable AbsolutePosition property.
   rstAuthors.CursorLocation = adUseClient
   rstAuthors.Open "authors", strCnn, , , adCmdTable

   ' Show current record information and get user's method choice.
   Do While True

      strMessage = "Name: " & rstAuthors!au_fName & " " & _
         rstAuthors!au_lName & vbCr & "Record " & _
         rstAuthors.AbsolutePosition & " of " & _
         rstAuthors.RecordCount & vbCr & vbCr & _
         "[1 - MoveFirst, 2 - MoveLast, " & vbCr & _
         "3 - MoveNext, 4 - MovePrevious]"
      intCommand = Val(Left(InputBox(strMessage), 1))
      If intCommand < 1 Or intCommand > 4 Then Exit Do

      ' Call method based on user's input.
      MoveAny intCommand, rstAuthors
   Loop
   rstAuthors.Close

End Sub

Public Sub MoveAny(intChoice As Integer, _
   rstTemp As Recordset)

   ' Use specified method, trapping for BOF and EOF.
   Select Case intChoice
      Case 1
         rstTemp.MoveFirst
      Case 2
         rstTemp.MoveLast
      Case 3
         rstTemp.MoveNext
         If rstTemp.EOF Then
            MsgBox "Already at end of recordset!"
            rstTemp.MoveLast
         End If
      Case 4
         rstTemp.MovePrevious
         If rstTemp.BOF Then
            MsgBox "Already at beginning of recordset!"
            rstTemp.MoveFirst
         End If
   End Select

End Sub

VBScript Version

Here is the same example written in VBScript to be used in an Active Server Page (ASP). To view this fully functional example, you need to create a system Data Source Name (DSN) called AdvWorks using the data source AdvWorks.mdb installed with IIS and located at C:\InetPub\ASPSamp\AdvWorks. This is a Microsoft Access database file. Use Find to locate the file Adovbs.inc and place it in the directory you plan to use. Cut and paste the following code to Notepad or another text editor and save it as MoveOne.asp. You can view the result in any client browser.

Try moving beyond the upper or lower limits of the recordset to see error handling work.

<!-- #Include file="ADOVBS.INC" -->
<% Language = VBScript %>
<HTML><HEAD>
<TITLE>ADO MoveNext MovePrevious MoveLast MoveFirst Methods</TITLE></HEAD>
<BODY>
<FONT FACE="MS SANS SERIF" SIZE=2>
<Center>
<H3>ADO Methods<BR>MoveNext MovePrevious MoveLast MoveFirst</H3>
<!-- Create Connection and Recordset Objects on Server -->
<%
 'Create and Open Connection Object
Set OBJdbConnection = Server.CreateObject("ADODB.Connection")
OBJdbConnection.Open "AdvWorks"
'Create and Open Recordset Object
Set RsCustomerList = Server.CreateObject("ADODB.Recordset")
RsCustomerList.ActiveConnection = OBJdbConnection
RsCustomerList.CursorType = adOpenKeyset
RsCustomerList.LockType = adLockOptimistic
RsCustomerList.Source = "Customers"

RsCustomerList.Open

' Check Request.Form collection to see if any moves are recorded

If Not IsEmpty(Request.Form("MoveAmount")) Then
'Keep track of the number and direction of moves this session

   Session("Moves") = Session("Moves") + Request.Form("MoveAmount")

   Clicks = Session("Moves")
'Move to last known position
   RsCustomerList.Move CInt(Clicks)
'Check if move is + or - and do error checking
      If CInt(Request.Form("MoveAmount")) = 1 Then

         If RsCustomerList.EOF Then
            Session("Moves") = RsCustomerList.RecordCount
            RsCustomerList.MoveLast
         End If

         RsCustomerList.MoveNext
      End If

      If Request.Form("MoveAmount") < 1 Then

         RsCustomerList.MovePrevious
      End If
'Check if First Record or Last Record Command Buttons Clicked
      If Request.Form("MoveLast") = 3 Then
         RsCustomerList.MoveLast
         Session("Moves") = RsCustomerList.RecordCount
      End If
      If Request.Form("MoveFirst") = 2 Then
         RsCustomerList.MoveFirst
         Session("Moves") = 1
      End If

End If
' Do Error checking for combination of Move Button clicks
      If RsCustomerList.EOF Then
         Session("Moves") = RsCustomerList.RecordCount
         RsCustomerList.MoveLast
         Response.Write "This is the Last Record"
         End If

      If RsCustomerList.BOF Then
         Session("Moves") = 1
         RsCustomerList.MoveFirst
         Response.Write "This is the First Record"
      End If

%>

<H3>Current Record Number is <BR>
<!-- Display Current Record Number and Recordset Size -->
<% If IsEmpty(Session("Moves"))  Then
Session("Moves") = 1
End If
%>

<%Response.Write(Session("Moves") )%> of <%=RsCustomerList.RecordCount%></H3>
<HR>

<Center><TABLE COLSPAN=8 CELLPADDING=5 BORDER=0>

<!-- BEGIN column header row for Customer Table-->

<TR><TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Company Name</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Contact Name</FONT>
</TD>
<TD ALIGN=CENTER WIDTH=150 BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Phone Number</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>City</FONT>
</TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>State/Province</FONT>
</TD></TR>

<!--Display ADO Data from Customer Table-->

  <TR>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RSCustomerList("CompanyName")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("ContactLastName") & ", " %>
  <%= RScustomerList("ContactFirstName") %>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>

  <%= RScustomerList("PhoneNumber")%>
 </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("City")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("StateOrProvince")%>
  </FONT></TD>
  </TR> </Table></FONT>

<HR>
<Input Type = Button Name = cmdDown  Value = "<  ">
<Input Type = Button Name = cmdUp Value = "  >">
<BR>
<Input Type = Button Name = cmdFirst Value = "First Record">

<Input Type = Button Name = cmdLast Value = "Last Record">
<H5>Click Direction Arrows to Use MovePrevious or MoveNext
<BR> </H5>

<!-- Use Hidden Form Fields to send values to Server -->

<Form Method = Post Action="MoveOne.asp" Name=Form>
<Input Type="Hidden" Size="4" Name="MoveAmount" Value = 0>
<Input Type="Hidden" Size="4" Name="MoveLast" Value = 0>
<Input Type="Hidden" Size="4" Name="MoveFirst" Value = 0>
</Form></BODY>

<Script Language = "VBScript">

Sub cmdDown_OnClick
'Set Values in Form Input Boxes and Submit Form
   Document.Form.MoveAmount.Value = -1
   Document.Form.Submit
End Sub

Sub cmdUp_OnClick

   Document.Form.MoveAmount.Value = 1
   Document.Form.Submit

End Sub

Sub cmdFirst_OnClick

   Document.Form.MoveFirst.Value = 2
   Document.Form.Submit

End Sub

Sub cmdLast_OnClick

   Document.Form.MoveLast.Value = 3
   Document.Form.Submit

End Sub
</Script></HTML>


NextRecordset Method Example

This example uses the NextRecordset method to view the data in a recordset that uses a compound command statement made up of three separate SELECT statements.

Public Sub NextRecordsetX()

   Dim rstCompound As ADODB.Recordset
   Dim strCnn As String
   Dim intCount As Integer

   ' Open compound recordset.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "

   Set rstCompound = New ADODB.Recordset
   rstCompound.Open "SELECT * FROM authors; " & _
      "SELECT * FROM stores; " & _
      "SELECT * FROM jobs", strCnn, , , adCmdText

   ' Display results from each SELECT statement.
   intCount = 1
   Do Until rstCompound Is Nothing
      Debug.Print "Contents of recordset #" & intCount
      Do While Not rstCompound.EOF
         Debug.Print , rstCompound.Fields(0), _
            rstCompound.Fields(1)
         rstCompound.MoveNext
      Loop

      Set rstCompound = rstCompound.NextRecordset
      intCount = intCount + 1
   Loop

End Sub


NumericScale and Precision Properties Example

This example uses the NumericScale and Precision properties to display the numeric scale and precision of fields in the Discounts table of the Pubs database.

Public Sub NumericScaleX()

   Dim rstDiscounts As ADODB.Recordset
   Dim fldTemp As ADODB.Field
   Dim strCnn As String

   ' Open recordset.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstDiscounts = New ADODB.Recordset
   rstDiscounts.Open "discounts", strCnn, , , adCmdTable

   ' Display numeric scale and precision of
   ' numeric and small integer fields.
   For Each fldTemp In rstDiscounts.Fields
      If fldTemp.Type = adNumeric _
         Or fldTemp.Type = adSmallInt Then
         MsgBox "Field: " & fldTemp.Name & vbCr & _
            "Numeric scale: " & _
               fldTemp.NumericScale & vbCr & _
            "Precision: " & fldTemp.Precision
      End If
   Next fldTemp

   rstDiscounts.Close

End Sub


Open and Close Methods Example

This example uses the Open and Close methods on both Recordset and Connection objects that have been opened.

Public Sub OpenX()

   Dim cnn1 As ADODB.Connection
   Dim rstEmployees As ADODB.Recordset
   Dim strCnn As String
   Dim varDate As Variant

   ' Open connection.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set cnn1 = New ADODB.Connection
   cnn1.Open strCnn

   ' Open employee table.
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.CursorType = adOpenKeyset
   rstEmployees.LockType = adLockOptimistic
   rstEmployees.Open "employee", cnn1, , , adCmdTable

   ' Assign the first employee record's hire date
   ' to a variable, then change the hire date.
   varDate = rstEmployees!hire_date
   Debug.Print "Original data"
   Debug.Print "  Name - Hire Date"
   Debug.Print "  " & rstEmployees!fName & " " & _
      rstEmployees!lName & " - " & rstEmployees!hire_date
   rstEmployees!hire_date = #1/1/1900#
   rstEmployees.Update
   Debug.Print "Changed data"
   Debug.Print "  Name - Hire Date"
   Debug.Print "  " & rstEmployees!fName & " " & _
      rstEmployees!lName & " - " & rstEmployees!hire_date

   ' Requery Recordset and reset the hire date.
   rstEmployees.Requery
   rstEmployees!hire_date = varDate
   rstEmployees.Update
   Debug.Print "Data after reset"
   Debug.Print "  Name - Hire Date"
   Debug.Print "  " & rstEmployees!fName & " " & _
      rstEmployees!lName & " - " & rstEmployees!hire_date

   rstEmployees.Close
   cnn1.Close

End Sub

VBScript Version

Here is the same example written in VBScript to be used in an Active Server Page (ASP). To view this fully functional example, you need to create a system Data Source Name (DSN) called AdvWorks using the data source AdvWorks.mdb installed with IIS and located at C:\InetPub\ASPSamp\AdvWorks. This is a Microsoft Access database file. Use Find to locate the file Adovbs.inc and place it in the directory you plan to use. Cut and paste the following code to Notepad or another text editor and save it as ADOOpen.asp. You can view the result in any client browser.

<!-- #Include file="ADOVBS.INC" -->
<HTML><HEAD>
<TITLE>ADO Open Method</TITLE>
</HEAD><BODY>
<FONT FACE="MS SANS SERIF" SIZE=2>
<Center><H3>ADO Open Method</H3>
<TABLE WIDTH=600 BORDER=0>
<TD VALIGN=TOP ALIGN=LEFT COLSPAN=3><FONT SIZE=2>
<!--- ADO Connection used to create 2 recordsets-->
<%
Set OBJdbConnection = Server.CreateObject("ADODB.Connection")
OBJdbConnection.Open "AdvWorks"
SQLQuery = "SELECT * FROM Customers"
'First Recordset RSCustomerList
Set RSCustomerList = OBJdbConnection.Execute(SQLQuery)
'Second Recordset RsProductist
Set RsProductList = Server.CreateObject("ADODB.Recordset")
RsProductList.CursorType = adOpenDynamic
RsProductList.LockType = adLockOptimistic
RsProductList.Open "Products", OBJdbConnection
%>
<TABLE COLSPAN=8 CELLPADDING=5 BORDER=0>

<!-- BEGIN column header row for Customer Table-->

<TR><TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Company Name</FONT></TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Contact Name</FONT></TD>
<TD ALIGN=CENTER WIDTH=150 BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>E-mail address</FONT></TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>City</FONT></TD>
<TD ALIGN=CENTER BGCOLOR="#008080">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>State/Province</FONT></TD></TR>

<!--Display ADO Data from Customer Table-->
<% Do While Not RScustomerList.EOF %>
  <TR><TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RSCustomerList("CompanyName")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("ContactLastName") & ", " %>
  <%= RScustomerList("ContactFirstName") %>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("ContactLastName")%>
 </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("City")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RScustomerList("StateOrProvince")%>
  </FONT></TD></TR>
<!-Next Row = Record Loop and add to html table-->
<%
RScustomerList.MoveNext
Loop
RScustomerList.Close
OBJdbConnection.Close
%>
</TABLE>
<HR>
<TABLE COLSPAN=8 CELLPADDING=5 BORDER=0>

<!-- BEGIN column header row for Product List Table-->

<TR><TD ALIGN=CENTER BGCOLOR="#800000">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Product Type</FONT></TD>
<TD ALIGN=CENTER BGCOLOR="#800000">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Product Name</FONT></TD>
<TD ALIGN=CENTER WIDTH=350 BGCOLOR="#800000">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Product Description</FONT></TD>
<TD ALIGN=CENTER BGCOLOR="#800000">
<FONT STYLE="ARIAL NARROW" COLOR="#ffffff" SIZE=1>Unit Price</FONT></TD></TR>
<!-- Display ADO Data Product List-->
<% Do While Not RsProductList.EOF %>
  <TR>  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RsProductList("ProductType")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RsProductList("ProductName")%>
  </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
   <%= RsProductList("ProductDescription")%>
 </FONT></TD>
  <TD BGCOLOR="f7efde" ALIGN=CENTER>
  <FONT STYLE="ARIAL NARROW" SIZE=1>
  <%= RsProductList("UnitPrice")%>
  </FONT></TD>

<!--  Next Row = Record -->
<%
RsProductList.MoveNext
Loop
'Remove Objects from Memory Freeing
Set RsProductList = Nothing
Set OBJdbConnection = Nothing
%>
</TABLE></FONT></Center></BODY></HTML>


OpenSchema Method Example

This example uses the OpenSchema method to display the name and type of each table in the Pubs database.

Public Sub OpenSchemaX()

   Dim cnn1 As ADODB.Connection
   Dim rstSchema As ADODB.Recordset
   Dim strCnn As String

   Set cnn1 = New ADODB.Connection
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn

   Set rstSchema = cnn1.OpenSchema(adSchemaTables)

   Do Until rstSchema.EOF
      Debug.Print "Table name: " & _
         rstSchema!TABLE_NAME & vbCr & _
         "Table type: " & rstSchema!TABLE_TYPE & vbCr
      rstSchema.MoveNext
   Loop
   rstSchema.Close

   cnn1.Close

End Sub

This example specifies a TABLE_TYPE query constraint in the OpenSchema method Criteria argument. As a result, only schema information for the Views specified in the Pubs database are returned. The example then displays the name(s) and type(s) of these table(s).

Public Sub OpenSchemaX2()

   Dim cnn2 As ADODB.Connection
   Dim rstSchema As ADODB.Recordset
   Dim strCnn As String

   Set cnn2 = New ADODB.Connection
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn2.Open strCnn

   Set rstSchema = cnn2.OpenSchema(adSchemaTables, Array(Empty, Empty, Empty, "VIEW"))

      Do Until rstSchema.EOF
         Debug.Print "Table name: " & _
            rstSchema!TABLE_NAME & vbCr & _
            "Table type: " & rstSchema!TABLE_TYPE & vbCr
         rstSchema.MoveNext
      Loop
   rstSchema.Close

   cnn2.Close

End Sub


OriginalValue and UnderlyingValue Properties Example

This example demonstrates the OriginalValue and UnderlyingValue properties by displaying a message if a record's underlying data has changed during a Recordset batch update.

Public Sub OriginalValueX()

   Dim cnn1 As ADODB.Connection
   Dim rstTitles As ADODB.Recordset
   Dim fldType As ADODB.Field
   Dim strCnn As String

   ' Open connection.
   Set cnn1 = New ADODB.Connection
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn

   ' Open recordset for batch update.
   Set rstTitles = New ADODB.Recordset
   Set rstTitles.ActiveConnection = cnn1
   rstTitles.CursorType = adOpenKeyset
   rstTitles.LockType = adLockBatchOptimistic
   rstTitles.Open "titles"

   ' Set field object variable for Type field.
   Set fldType = rstTitles!Type

   ' Change the type of psychology titles.
   Do Until rstTitles.EOF
      If Trim(fldType) = "psychology" Then
         fldType = "self_help"
      End If
      rstTitles.MoveNext
   Loop

   ' Similate a change by another user by updating
   ' data using a command string.
   cnn1.Execute "UPDATE titles SET type = 'sociology' " & _
      "WHERE type = 'psychology'"

   'Check for changes.
   rstTitles.MoveFirst
   Do Until rstTitles.EOF
      If fldType.OriginalValue <> _
         fldType.UnderlyingValue Then

         MsgBox "Data has changed!" & vbCr & vbCr & _
            "  Title ID: " & rstTitles!title_id & vbCr & _
            "  Current value: " & fldType & vbCr & _
            "  Original value: " & _
            fldType.OriginalValue & vbCr & _
            "  Underlying value: " & _
            fldType.UnderlyingValue & vbCr
      End If
      rstTitles.MoveNext
   Loop

   ' Cancel the update because this is a demonstration.
   rstTitles.CancelBatch
   rstTitles.Close

   ' Restore original values.
   cnn1.Execute "UPDATE titles SET type = 'psychology' " & _
      "WHERE type = 'sociology'"

   cnn1.Close

End Sub


Prepared Property Example

This example demonstrates the Prepared property by opening two Command objects—one prepared and one not prepared.

Public Sub PreparedX()

   Dim cnn1 As ADODB.Connection
   Dim cmd1 As ADODB.Command
   Dim cmd2 As ADODB.Command
   Dim strCnn As String
   Dim strCmd As String
   Dim sngStart As Single
   Dim sngEnd As Single
   Dim sngNotPrepared As Single
   Dim sngPrepared As Single
   Dim intLoop As Integer

   ' Open a connection.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set cnn1 = New ADODB.Connection
   cnn1.Open strCnn

   ' Create two command objects for the same
   ' command -- one prepared and one not prepared.
   strCmd = "SELECT title, type FROM titles ORDER BY type"

   Set cmd1 = New ADODB.Command
   Set cmd1.ActiveConnection = cnn1
   cmd1.CommandText = strCmd

   Set cmd2 = New ADODB.Command
   Set cmd2.ActiveConnection = cnn1
   cmd2.CommandText = strCmd
   cmd2.Prepared = True

   ' Set a timer, then execute the unprepared
   ' command 20 times.
   sngStart = Timer
   For intLoop = 1 To 20
      cmd1.Execute
   Next intLoop
   sngEnd = Timer
   sngNotPrepared = sngEnd - sngStart

   ' Reset the timer, then execute the prepared
   ' command 20 times.
   sngStart = Timer
   For intLoop = 1 To 20
      cmd2.Execute
   Next intLoop
   sngEnd = Timer
   sngPrepared = sngEnd - sngStart

   ' Display performance results.
   MsgBox "Performance Results:" & vbCr & _
      "   Not Prepared: " & Format(sngNotPrepared, _
      "##0.000") & " seconds" & vbCr & _
      "   Prepared: " & Format(sngPrepared, _
      "##0.000") & " seconds"

   cnn1.Close

End Sub


Provider and DefaultDatabase Properties Example

This example demonstrates the Provider property by opening three Connection objects using different providers. It also uses the DefaultDatabase property to set the default database for the Microsoft ODBC Provider.

Public Sub ProviderX()

   Dim cnn1 As ADODB.Connection
   Dim cnn2 As ADODB.Connection
Dim cnn3 As ADODB.Connection

   ' Open a connection using the Microsoft ODBC provider.
   Set cnn1 = New ADODB.Connection
   cnn1.ConnectionString = "driver={SQL Server};" & _
      "server=bigsmile;uid=sa;pwd=pwd"
   cnn1.Open strCnn
   cnn1.DefaultDatabase = "pubs"

   ' Display the provider.
   MsgBox "Cnn1 provider: " & cnn1.Provider

   ' Open a connection using the Microsoft Jet provider.
   Set cnn2 = New ADODB.Connection
   cnn2.Provider = "Microsoft.Jet.OLEDB.3.51"
   cnn2.Open "C:\Samples\northwind.mdb", "admin", ""

   ' Display the provider.
   MsgBox "Cnn2 provider: " & cnn2.Provider

   ' Open a connection using the Microsoft SQL Server provider.
   Set cnn3 = New ADODB.Connection
   cnn3.Provider = "sqloledb"
   cnn3.Open "Data Source=srv;Initial Catalog=pubs;", "sa", ""

   ' Display the provider.
   MsgBox "Cnn3 provider: " & cnn3.Provider

   cnn1.Close
   cnn2.Close
   cnn3.Close

End Sub


RDS.DataControl Object Example (VBScript)

The following code shows how to set the RDS.DataControl parameters at design time and bind it to a data-aware control using an ODBC data source called ADCDemo. If you followed directions, ADCDemo is installed on your server as a SQL Server ODBC data source. Cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi1.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples</H2>
<HR><BR>
<H3>Remote Data Service</H3>
<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
</OBJECT>
<!-- Remote Data Service with Parameters set at Design Time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
   <PARAM NAME="SQL" VALUE="Select * from Employee for browse">
   <PARAM NAME="SERVER" VALUE="http://<%=Request.ServerVariables("SERVER_NAME")%>">
   <PARAM NAME="CONNECT" VALUE="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;">
</OBJECT><BR><HR></Center>

The following example shows how to set the necessary parameters of RDS.DataControl at run time. To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi2.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples </H2>
<HR><BR>
<H3>Remote Data Service Run Time</H3>
<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE="Remote Data Service Run Time">
</OBJECT>

<!-- RDS.DataControl with no parameters set at design time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
   </OBJECT>
<HR>
<Input Size=70 Name="txtServer" Value="http://<%=Request.ServerVariables("SERVER_NAME")%>"><BR>
<Input Size=70 Name="txtConnect" Value="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;">
<BR>
<Input Size=70 Name="txtSQL" Value="Select * from Employee">
<HR>
<INPUT TYPE=BUTTON NAME="Run" VALUE="Run"><BR>
<H4>Fill Grid with these values or change them to see data from another ODBC data source on your server</H4>
</Center>
<Script Language="VBScript">
<!--
' Set parameters of RDS.DataControl at Run Time
Sub Run_OnClick
   ADC.Server = txtServer.Value
   ADC.SQL = txtSQL.Value
   ADC.Connect = txtConnect.Value
   ADC.Refresh
End Sub
-->
</Script>


RDS.DataSpace Object and CreateObject Method Example (VBScript)

The following example shows how to use the CreateObject method of the RDS.DataSpace with the default business object, RDSServer.DataFactory. To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi8.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples </H2>
<HR><H3>Using Query Method of RDSServer.DataFactory</H3>

<!-- RDS.DataSpace  ID ADS1-->
<OBJECT ID="ADS1" WIDTH=1 HEIGHT=1
CLASSID="CLSID:BD96C556-65A3-11D0-983A-00C04FC29E36">
</OBJECT>

<!-- RDS.DataControl with parameters set at run time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
</OBJECT>

<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE="RDSServer.DataFactory Run Time">
</OBJECT>
<HR>
<INPUT TYPE=BUTTON NAME="Run" VALUE="Run"><BR>
<H4>Click Run. The CreateObject Method of the RDS.DataSpace Object Creates an instance of the RDSServer.DataFactory.
The Query Method of the RDSServer.DataFactory is used to bring back a Recordset. </H4>
</Center>
<Script Language="VBScript">
<!--
Dim ADF
Dim strServer
Dim strConnect
Dim strSQL
strServer = "http://<%=Request.ServerVariables("SERVER_NAME")%>"
strConnect = "dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;"
strSQL = "Select * from Employee"

Sub Run_OnClick()
   Dim objADORs      'Create Recordset Object
Set ADF = ADS1.CreateObject("RDSServer.DataFactory", strServer)            'Get Recordset
Set objADORs = ADF.Query(strConnect, strSQL)
' Use  RDS.DataControl to bind Recordset to Data
' Aware Grid Control

   ADC.SourceRecordset = objADORs

End Sub
-->
</Script>

The following example shows how to use the CreateObject method to create an instance of a custom business object, VbBusObj.VbBusObjCls. It also uses the Active Server Pages scripting to identify the Web server name. To see the complete example, choose “VBScript in Internet Explorer” in the Client Tier column and “Custom Visual Basic Business Object” in the Middle Tier column from the sample applications selector.

Sub Window_OnLoad()
   strServer = "http://<%=Request.ServerVariables("SERVER_NAME")%>"
   Set BO = ADS1.CreateObject("VbBusObj.VbBusObjCls", strServer)
   txtConnect.Value = "dsn=pubs;uid=sa;pwd=;"
   txtGetRecordset.Value = "Select * From authors for Browse"
End Sub


RDSServer.DataFactory Object, Query Method, and CreateObject Method Example (VBScript)

This example creates an RDSServer.DataFactory object using the CreateObject method of the RDS.DataSpace object. To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi7.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples</H2>
<HR><H3>Using Query Method of RDSServer.DataFactory</H3>

<!-- RDS.DataSpace  ID ADS1-->
<OBJECT ID="ADS1" WIDTH=1 HEIGHT=1
CLASSID="CLSID:BD96C556-65A3-11D0-983A-00C04FC29E36">
</OBJECT>

<!-- RDS.DataControl with parameters
set at run time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
</OBJECT>

<Object classid ="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables _
   ("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE=" RDSServer.DataFactory Run Time">
</OBJECT>
<HR>
<INPUT TYPE=BUTTON NAME="Run" VALUE="Run"><BR>
<H4>Click Run. The CreateObject Method of the
RDS.DataSpace Object Creates an instance of the
RDSServer.DataFactory.
The Query Method of the RDSServer.DataFactory is used
to bring back a Recordset. </H4>
</Center>
<Script Language="VBScript">
<!--
Dim ADF
Dim strServer
Dim strConnect
Dim strSQL

strServer = "http://<%=Request.ServerVariables _
("SERVER_NAME")%>"
strConnect = "dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;"
strSQL = "Select * from Employee"

Sub Run_OnClick()
' Create RDSServer.DataFactory Object
   Dim objADORs
' Get Recordset
Set ADF = ADS1.CreateObject("RDSServer.DataFactory", strServer)
Set objADORs = ADF.Query(strConnect, strSQL)
' Set parameters of RDS.DataControl at Run Time
   ADC.Server = strServer
   ADC.SQL = strSQL
   ADC.Connect = strConnect
   ADC.Refresh
End Sub
-->
</Script>


ReadyState Property Example

The following example shows how to read the ReadyState property of the RDS.DataControl object at run time in VBScript code. ReadyState is a read-only property.

To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi9.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples </H2>
<HR>
<H3> RDS.DataControl ReadyState property</H3></Center>
<!-- RDS.DataControl with parameters set at design time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
   <PARAM NAME="SQL" VALUE="Select * from Employee for browse">
   <PARAM NAME="SERVER" VALUE="http://<%=Request.ServerVariables("SERVER_NAME")%>">
   <PARAM NAME="CONNECT" VALUE="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;">
<PARAM NAME="ExecuteOptions" VALUE="adcExecAsync">
<PARAM NAME="FetchOptions" VALUE="adcFetchAsync">
</OBJECT>

<Script Language="VBScript">

Sub Window_OnLoad
Select Case ADC1.ReadyState
   case 2: MsgBox "Executing Query"
   case 3: MsgBox "Fetching records in background"
   case 4: MsgBox "All records fetched"
End Select
End Sub
</Script>


Recordset and SourceRecordset Properties Example

The following example shows how to set the necessary parameters of the RDSServer.DataFactory default business object at run time. To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi4.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples</H2>
<HR>
<H3>Using SourceRecordset and Recordset with RDSServer.DataFactory</H3>
<!-- RDS.DataSpace ID ADS1 -->
<OBJECT ID="ADS1" WIDTH=1 HEIGHT=1
CLASSID="CLSID:BD96C556-65A3-11D0-983A-00C04FC29E36">
</OBJECT>

<!-- RDS.DataControl with parameters set at run time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
</OBJECT>

<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE="RDSServer.DataFactory Run Time">
</OBJECT>
<HR>
<Input Size=70 Name="txtServer" Value="http://<%=Request.ServerVariables("SERVER_NAME")%>"><BR>
<Input Size=70 Name="txtConnect" Value="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;"><BR>
<Input Size=70 Name="txtSQL" Value="Select * from Employee">
<HR>
<INPUT TYPE=BUTTON NAME="Run" VALUE="Run"><BR>
<H4>Fill Grid with these values or change them to see data from another ODBC data source on your server.
<BR>Try dsn=pubs;uid=sa;pwd=; and Select * From Authors</H4>
</Center>
<Script Language="VBScript">
<!--
Dim ADF
Dim strServer
strServer = "http://<%=Request.ServerVariables("SERVER_NAME")%>"

Sub Run_OnClick()
   Dim objADORs         ' Create RDSServer.DataFactory Object
Set ADF = ADS1.CreateObject("RDSServer.DataFactory", strServer)               ' Get Recordset
Set objADORs = ADF.Query(txtConnect.Value,txtSQL.Value)

' Set parameters of RDS.DataControl at Run Time
   ADC.Server = txtServer.Value
   ADC.SQL = txtSQL.Value
   ADC.Connect = txtConnect.Value
   ADC.Refresh
End Sub
-->
</Script>


Refresh Method Example (Visual Basic)

This example demonstrates using the Refresh method to refresh the Parameters collection for a stored procedure Command object.

Public Sub RefreshX()

   Dim cnn1 As ADODB.Connection
   Dim cmdByRoyalty As ADODB.Command
   Dim rstByRoyalty As ADODB.Recordset
   Dim rstAuthors As ADODB.Recordset
   Dim intRoyalty As Integer
   Dim strAuthorID As String
   Dim strCnn As String

   ' Open connection.
   Set cnn1 = New ADODB.Connection
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn

   ' Open a command object for a stored procedure
   ' with one parameter.
   Set cmdByRoyalty = New ADODB.Command
   Set cmdByRoyalty.ActiveConnection = cnn1
   cmdByRoyalty.CommandText = "byroyalty"
   cmdByRoyalty.CommandType = adCmdStoredProc
   cmdByRoyalty.Parameters.Refresh

   ' Get paramater value and execute the command,
   ' storing the results in a recordset.
   intRoyalty = Trim(InputBox("Enter royalty:"))
   cmdByRoyalty.Parameters(1) = intRoyalty
   Set rstByRoyalty = cmdByRoyalty.Execute()

   ' Open the Authors table to get author names for display.
   Set rstAuthors = New ADODB.Recordset
   rstAuthors.Open "authors", cnn1, , , adCmdTable

   ' Print current data in the recordset, adding
   ' author names from Authors table.
   Debug.Print "Authors with " & intRoyalty & " percent royalty"
   Do While Not rstByRoyalty.EOF
      strAuthorID = rstByRoyalty!au_id
      Debug.Print "   " & rstByRoyalty!au_id & ", ";
      rstAuthors.Filter = "au_id = '" & strAuthorID & "'"
      Debug.Print rstAuthors!au_fname & " " & _
         rstAuthors!au_lname
      rstByRoyalty.MoveNext
   Loop

   rstByRoyalty.Close
   rstAuthors.Close
   cnn1.Close

End Sub


Refresh Method Example (VBScript)

The following example shows how to set the necessary parameters of RDS.DataControl at run time. The manner in which a Recordset is retrieved using the Refresh method is determined by the settings of the ExecuteOptions and FetchOptions properties. To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi2.asp. ASP script will identify your server.

<HTML>
<HEAD>
<TITLE>Refresh / ExecuteOptions</TITLE>
</HEAD>
<BODY>
<Center><H2>RDS API Code Examples </H2>
<HR>
<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE="Remote Data Service Run Time">
</OBJECT>

<!-- RDS.DataControl with no parameters set at design time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
   </OBJECT>
<HR>
<Input Size=70 Name="txtServer" Value="http://<%=Request.ServerVariables("SERVER_NAME")%>"><BR>
<Input Size=70 Name="txtConnect" Value = "dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;"><BR>
<Input Size=70 Name="txtSQL" Value="Select * from Employee">
<BR>
Choose if you want the Recordset brought back Synchronously on the current calling thread or Asynchronously on another thread
<Input Type="Radio" Name="optExecuteOptions" Checked OnClick="SetExO('adcExecSync')">
<Input Type="Radio" Name="optExecuteOptions"  OnClick="SetExO('adcExecAsync')"><BR>
Fetch Up Front, Background Fetch with Blocking or Background Fetch without Blocking
<Input Type="Radio" Name="optFetchOptions"  OnClick="SetFO('adcFetchUpFront')">
<Input Type="Radio" Name="optFetchOptions" Checked OnClick="SetFO('adcFetchBackground')">
<Input Type="Radio" Name="optFetchOptions"  OnClick="SetFO('adcFetchAsync')">

<HR>
<INPUT TYPE=BUTTON NAME="Run" VALUE="Run"><BR>
<H4>Fill Grid with these values or change them to see data from another ODBC data source on your server</H4>
</Center>
<Script Language="VBScript">
<!--
Dim EO          'ExecuteOptions
Dim FO         'FetchOptions
EO = "adcExecSync"   'Default value
FO = "adcFetchBackground"   'Default value
Sub SetExO(NewEO)
   EO = NewEO
End Sub
Sub SetFO(NewFO)
   FO = NewFO
End Sub

' Set parameters of RDS.DataControl at Run Time
Sub Run_OnClick
   ADC.Server = txtServer.Value
   ADC.SQL = txtSQL.Value
   ADC.Connect = txtConnect.Value
If EO = "adcExecSync" Then      'Determine which ExecuteOption chosen
   ADC.ExecuteOptions = adcExecSync
      MsgBox "Recordset brought in on current calling thread Syncronously"
Else
   ADC.ExecuteOptions = adcExecAsync
         MsgBox "Recordset brought in on another thread Asyncronously"
End If

If FO = "adcFetchBackground" Then      'Determine                               ‘which FetchOption chosen
   ADC.FetchOptions = adcFetchBackground
      MsgBox "Control goes back to user after first batch of records returned"
ElseIf FO = " adcFetchUpFront" Then
   ADC.FetchOptions = adcFetchUpFront
         MsgBox "All records returned before control goes back to user"
Else
   ADC.FetchOptions = adcFetchAsync
         MsgBox "Control goes back to user immediately"
End If

ADC.Refresh

End Sub
-->
</Script>
</BODY>
</HTML>


Resync Method Example

This example demonstrates using the Resync method to refresh data in a static recordset.

Public Sub ResyncX()

   Dim strCnn As String
   Dim rstTitles As ADODB.Recordset

   ' Open connections.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "

   ' Open recordset for titles table.
   Set rstTitles = New ADODB.Recordset
   rstTitles.CursorType = adOpenStatic
   rstTitles.LockType = adLockBatchOptimistic
   rstTitles.Open "titles", strCnn, , , adCmdTable

   ' Change the type of the first title in the recordset.
   rstTitles!Type = "database"

   ' Display the results of the change.
   MsgBox "Before resync: " & vbCr & vbCr & _
      "Title - " & rstTitles!Title & vbCr & _
      "Type - " & rstTitles!Type

   ' Resync with database and redisplay results.
   rstTitles.Resync
   MsgBox "After resync: " & vbCr & vbCr & _
      "Title - " & rstTitles!Title & vbCr & _
      "Type - " & rstTitles!Type

   rstTitles.CancelBatch
   rstTitles.Close

End Sub


Server Property Example

The following code shows how to set the RDS.DataControl parameter at design time and bind it to a data-aware control using an ODBC system data source called ADCDemo. If you followed directions, ADCDemo is installed on your server as a SQL Server ODBC system data source. Cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi1.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples </H2>
<HR><BR>
<H3>Remote Data Service</H3>
<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
</OBJECT>
<!-- Remote Data Service with Parameters set at Design Time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
   <PARAM NAME="SQL" VALUE="Select * from Employee for browse">
   <PARAM NAME="SERVER" VALUE="http://<%=Request.ServerVariables("SERVER_NAME")%>">
   <PARAM NAME="CONNECT" VALUE="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;">
</OBJECT><BR><HR></Center>

The following example shows how to set the necessary parameters of RDS.DataControl at run time. To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi4.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples </H2>
<HR><H3>Remote Data Service Server Property Set at Run Time</H3>
<!-- RDS.DataControl with no parameters set at design time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
</OBJECT>
<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE="Remote Data Service Run Time">
</OBJECT><HR>
<Input Size=70 Name="txtServer"><BR>
<Input Size=70 Name="txtConnect" Value="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;">
<BR>
<Input Size=70 Name="txtSQL" Value="Select * from Employee">
<HR>
<INPUT TYPE=BUTTON NAME="Run" VALUE="Run"><BR>
<H4>Fill top text box with your Web server name in the form http://Myserver</H4>
</Center>
<Script Language="VBScript">
<!--
' Set parameters of RDS.DataControl at Run Time
Sub Run_OnClick
   ADC.Server = txtServer.Value
   ADC.SQL = txtSQL.Value
   ADC.Connect = txtConnect.Value
   ADC.Refresh
End Sub
-->
</Script>


Source Property Example

This example demonstrates the Source property by opening three Recordset objects based on different data sources.

Public Sub SourceX()

   Dim cnn1 As ADODB.Connection
   Dim rstTitles As ADODB.Recordset
   Dim rstPublishers As ADODB.Recordset

Dim rstPublishersDirect As ADODB.Recordset

   Dim rstTitlesPublishers As ADODB.Recordset
   Dim cmdSQL As ADODB.Command
   Dim strCnn As String
   Dim strSQL As String

   ' Open a connection.
   Set cnn1 = New ADODB.Connection
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn

   ' Open a recordset based on a command object.
   Set cmdSQL = New ADODB.Command
   Set cmdSQL.ActiveConnection = cnn1
   cmdSQL.CommandText = "Select title, type, pubdate " & _
      "FROM titles ORDER BY title"
   Set rstTitles = cmdSQL.Execute()

   ' Open a recordset based on a table.
   Set rstPublishers = New ADODB.Recordset
   rstPublishers.Open "publishers", strCnn, , , adCmdTable

   ' Open a recordset based on a table.
   Set rstPublishersDirect = New ADODB.Recordset
   rstPublishersDirect.Open "publishers", strCnn, , , adCmdTableDirect

   ' Open a recordset based on an SQL string.
   Set rstTitlesPublishers = New ADODB.Recordset
   strSQL = "SELECT title_ID AS TitleID, title AS Title, " & _
      "publishers.pub_id AS PubID, pub_name AS PubName " & _
      "FROM publishers INNER JOIN titles " & _
      "ON publishers.pub_id = titles.pub_id " & _
      "ORDER BY Title"
   rstTitlesPublishers.Open strSQL, strCnn, , , adCmdText

   ' Use the Source property to display the source of each recordset.
   MsgBox "rstTitles source: " & vbCr & _
      rstTitles.Source & vbCr & vbCr & _
      "rstPublishers source: " & vbCr & _
      rstPublishers.Source & vbCr & vbCr & _
      "rstPublishersDirect source: " & vbCr & _
      rstPublishersDirect.Source & vbCr & vbCr & _
      "rstTitlesPublishers source: " & vbCr & _
      rstTitlesPublishers.Source

   rstTitles.Close
   rstPublishers.Close
   rstTitlesPublishers.Close
   cnn1.Close

End Sub


SQL Property Example

The following code shows how to set the RDS.DataControl parameter at design time and bind it to a data-aware control using an ODBC data source called Pubs that ships with SQL Server 6.5.

<!—- RDS.DataControl -- >
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33" ID=ADC HEIGHT=10 WIDTH=10>
   <PARAM NAME="SQL" VALUE="Select * from Authors">
   <PARAM NAME="SERVER" VALUE="http://MyWebServer">
<PARAM NAME="CONNECT" VALUE="dsn=pubs;UID=sa;PWD=;">
</OBJECT>

<!-- Data Grid -- >
<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://MyWebServer
/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="BackColor"   VALUE="-2147483643">
   <PARAM NAME="BackColorOdd"  VALUE="-2147483643">
   <PARAM NAME="ForeColorEven" VALUE="0">
</OBJECT>

The following example shows how to set the necessary parameters of RDS.DataControl at run time. To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi5.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples </H2>
<HR><H3>Remote Data Service SQL Property Set at Run Time</H3>

<!-- RDS.DataControl with no parameters set at design time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
</OBJECT>
<Object CLASSID="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE="Remote Data Service Run Time">
</OBJECT>
<HR>
<Input Size=70 Name="txtServer" Value= "http://<%=Request.ServerVariables("SERVER_NAME")%>">
<BR>
<Input Size=70 Name="txtConnect" Value="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;">
<BR>
<Input Size=70 Name="txtSQL">
<HR>
<INPUT TYPE=BUTTON NAME="Run" VALUE="Run"><BR>
<H4>Fill bottom text box with an SQL string<BR>
Try ... Select * from Employee</H4>
</Center>
<Script Language="VBScript">
<!--
' Set parameters of RDS. at Run Time
Sub Run_OnClick
   ADC.Server = txtServer.Value
   ADC.SQL = txtSQL.Value
   ADC.Connect = txtConnect.Value
   ADC.Refresh
End Sub
-->
</Script>


State Property Example

This example uses the State property to display a message while asynchronous connections are opening and asynchronous commands are executing.

Public Sub StateX()

   Dim cnn1 As ADODB.Connection
   Dim cnn2 As ADODB.Connection
   Dim cmdChange As ADODB.Command
   Dim cmdRestore As ADODB.Command
   Dim strCnn As String

   ' Open two asynchronous connections, displaying
   ' a message while connecting.
   Set cnn1 = New ADODB.Connection
   Set cnn2 = New ADODB.Connection
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "

   cnn1.Open strCnn, , , adAsyncConnect
   While (cnn1.State = adStateConnecting)
      Debug.Print "Opening first connection...."
   Wend

   cnn2.Open strCnn, , , adAsyncConnect
   While (cnn2.State = adStateConnecting)
      Debug.Print "Opening second connection...."
   Wend

   ' Create two command objects.
   Set cmdChange = New ADODB.Command
   cmdChange.ActiveConnection = cnn1
   cmdChange.CommandText = "UPDATE titles SET type = 'self_help' " & _
      "WHERE type = 'psychology'"

   Set cmdRestore = New ADODB.Command
   cmdRestore.ActiveConnection = cnn2
   cmdRestore.CommandText = "UPDATE titles SET type = 'psychology' " & _
      "WHERE type = 'self_help'"

   ' Executing the commands, displaying a message
   ' while they are executing.
   cmdChange.Execute , , adAsyncExecute
   While (cmdChange.State = adStateExecuting)
      Debug.Print "Change command executing...."
   Wend

   cmdRestore.Execute , , adAsyncExecute
   While (cmdRestore.State = adStateExecuting)
      Debug.Print "Restore command executing...."
   Wend

   cnn1.Close
   cnn2.Close

End Sub


Status Property Example

This example uses the Status property to display which records have been modified in a batch operation before a batch update has occurred.

Public Sub StatusX()

   Dim rstTitles As ADODB.Recordset
   Dim strCnn As String

   ' Open recordset for batch update.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstTitles = New ADODB.Recordset
   rstTitles.CursorType = adOpenKeyset
   rstTitles.LockType = adLockBatchOptimistic
   rstTitles.Open "titles", strCnn, , , adCmdTable

   ' Change the type of psychology titles.
   Do Until rstTitles.EOF
      If Trim(rstTitles!Type) = "psychology" Then
         rstTitles!Type = "self_help"
      End If
      rstTitles.MoveNext
   Loop

   ' Display Title ID and status.
   rstTitles.MoveFirst
   Do Until rstTitles.EOF
      If rstTitles.Status = adRecModified Then
         Debug.Print rstTitles!title_id & " - Modified"
      Else
         Debug.Print rstTitles!title_id
      End If
      rstTitles.MoveNext
   Loop

   ' Cancel the update because this is a demonstration.
   rstTitles.CancelBatch
   rstTitles.Close

End Sub


SubmitChanges Method Example (VBScript)

The following code fragment shows how to use the SubmitChanges method with an RDS.DataControl object.

To test this example, cut and paste this code between the <Body></Body> tags in a normal HTML document and name it ADCapi6.asp. ASP script will identify your server.

<Center><H2>RDS API Code Examples </H2>
<HR>
<H3>Remote Data Service SubmitChanges and CancelUpdate Methods</H3>
<!-- RDS.DataControl with parameters set at design time -->
<OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
   ID=ADC>
   <PARAM NAME="SQL" VALUE="Select * from Employee for browse">
   <PARAM NAME="SERVER" VALUE="http://<%=Request.ServerVariables("SERVER_NAME")%>">
   <PARAM NAME="CONNECT" VALUE="dsn=ADCDemo;UID=ADCDemo;PWD=ADCDemo;"> </OBJECT>

<Object classid ="clsid:AC05DC80-7DF1-11d0-839E-00A024A94B3A"
   CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>/MSADC/Samples/Sheridan.cab"
   ID=GRID1
      datasrc=#ADC
      HEIGHT=125
      WIDTH=495>
   <PARAM NAME="AllowAddNew" VALUE="TRUE">
   <PARAM NAME="AllowDelete" VALUE="TRUE">
   <PARAM NAME="AllowUpdate" VALUE="TRUE">
   <PARAM NAME="Caption" VALUE="Remote Data Service Run Time">
</OBJECT>
<HR>
<INPUT TYPE=BUTTON NAME="SubmitChange" VALUE="Submit-Changes"><INPUT TYPE=BUTTON NAME="CancelChange" VALUE="Cancel-Update"><BR>
<H4>Add a new person or alter a current entry on the grid. Move off that Row. <BR>
Submit the Changes to your DBMS or cancel the updates. </H4>
</Center>
<Script Language="VBScript">
<!--
' Set parameters of RDS.DataControl at Run Time
Sub SubmitChange_OnClick
   ADC.SubmitChanges
   ADC.Refresh
End Sub

Sub CancelUpdate_OnClick
   ADC.CancelUpdate
End Sub
-->
</Script>

The following code fragment shows how to use the SubmitChanges method with an RDSServer.DataFactory object. You may want to submit changes to the DRSServer.DataFactory if you are working on a Visual Basic project where the RDS.DataControl isn't used. To create this project, open a Visual Basic form and place on it a List box (List1), two Text boxes (txtConnect and txtGetRecordset), and two Command buttons (cmdGetRecordset and cmdSubmitChanges).

Dim ads As Object   ' RDS.DataSpace object
Dim adf As Object   ' RDSServer.DataFactory object

Private Sub UserDocument_Initialize()
   Call Form_Load
End Sub

Private Sub Form_Load()
   txtConnect.Text = "Dsn=pubs;Uid=sa;Pwd=;"
   txtGetRecordset.Text = "Select au_lname from authors"
End Sub

Private Sub cmdGetRecordset_Click()
   Dim Server As String
   Server = txtServer.Text

   ' Create RDS.DataSpace using CreateObject Method of RDS.DataSpace
   Set ads = CreateObject("RDS.DataSpace")
   Set adf = ads.CreateObject("RDSServer.DataFactory", Server)

   ' Populate ListBox with Recordset
   MousePointer = vbHourglass
   Dim objADORs As Object
   Set objADORs = adf.Query(CStr(txtConnect.Text), CStr(txtGetRecordset.Text))
   List1.Clear
   While Not objADORs.EOF
      List1.AddItem objADORs(0).Value
      objADORs.MoveNext
   Wend
   MousePointer = vbNormal
End Sub
Sub cmdSubmitChanges_OnClick
   adf.SubmitChanges " Dsn=pubs;Uid=sa;Pwd=;",_
   objADORs
End Sub


Supports Method Example

This example uses the Supports method to display the options supported by a recordset opened with different cursor types. The DisplaySupport procedure is required for this procedure to run.

Public Sub SupportsX()

   Dim aintCursorType(4) As Integer
   Dim rstTitles As ADODB.Recordset
   Dim strCnn As String
   Dim intIndex As Integer

   ' Open connections.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "

   ' Fill array with CursorType constants.
   aintCursorType(0) = adOpenForwardOnly
   aintCursorType(1) = adOpenKeyset
   aintCursorType(2) = adOpenDynamic
   aintCursorType(3) = adOpenStatic

   ' Open recordset using each CursorType and
   ' optimitic locking. Then call the DisplaySupport
   ' procedure to display the supported options.
   For intIndex = 0 To 3
      Set rstTitles = New ADODB.Recordset
      rstTitles.CursorType = aintCursorType(intIndex)
      rstTitles.LockType = adLockOptimistic
      rstTitles.Open "titles", strCnn, , , adCmdTable

      Select Case aintCursorType(intIndex)
         Case adOpenForwardOnly
            Debug.Print "ForwardOnly cursor supports:"
         Case adOpenKeyset
            Debug.Print "Keyset cursor supports:"
         Case adOpenDynamic
            Debug.Print "Dynamic cursor supports:"
         Case adOpenStatic
            Debug.Print "Static cursor supports:"
      End Select

      DisplaySupport rstTitles
      rstTitles.Close
   Next intIndex

End Sub

Public Sub DisplaySupport(rstTemp As ADODB.Recordset)

   Dim alngConstants(11) As Long
   Dim booSupports As Boolean
   Dim intIndex As Integer

   ' Fill array with cursor option constants.
   alngConstants(0) = adAddNew
   alngConstants(1) = adApproxPosition
   alngConstants(2) = adBookmark
   alngConstants(3) = adDelete
   alngConstants(4) = adFind
   alngConstants(5) = adHoldRecords
   alngConstants(6) = adMovePrevious
   alngConstants(7) = adNotify
   alngConstants(8) = adResync
   alngConstants(9) = adUpdate
   alngConstants(10) = adUpdateBatch

   For intIndex = 0 To 10
      booSupports = _
         rstTemp.Supports(alngConstants(intIndex))
      If booSupports Then
         Select Case alngConstants(intIndex)
            Case adAddNew
               Debug.Print "   AddNew"
            Case adApproxPosition
               Debug.Print "   AbsolutePosition and AbsolutePage"
            Case adBookmark
               Debug.Print "   Bookmark"
            Case adDelete
               Debug.Print "   Delete"
            Case adFind
               Debug.Print "   Find"
            Case adHoldRecords
               Debug.Print "   Holding Records"
            Case adMovePrevious
               Debug.Print "   MovePrevious and Move"
            Case adNotify
               Debug.Print "   Notifications"
            Case adResync
               Debug.Print "   Resyncing data"
            Case adUpdate
               Debug.Print "   Update"
            Case adUpdateBatch
               Debug.Print "   batch updating"
         End Select
      End If
   Next intIndex

End Sub


Type Property Example

This example demonstrates the Type property by displaying the name of the constant corresponding to the value of the Type property of all the Field objects in the Employee table. The FieldType function is required for this procedure to run.

Public Sub TypeX()

   Dim rstEmployees As ADODB.Recordset
   Dim fldLoop As ADODB.Field
   Dim strCnn As String

   ' Open recordset with data from Employee table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.Open "employee", strCnn, , , adCmdTable

   Debug.Print "Fields in Employee Table:" & vbCr

   ' Enumerate Fields collection of Employees table.
   For Each fldLoop In rstEmployees.Fields
      Debug.Print "  Name: " & fldLoop.Name & vbCr & _
         "  Type: " & FieldType(fldLoop.Type) & vbCr
   Next fldLoop

End Sub

Public Function FieldType(intType As Integer) As String

   Select Case intType
      Case adChar
         FieldType = "adChar"
      Case adVarChar
         FieldType = "adVarChar"
      Case adSmallInt
         FieldType = "adSmallInt"
      Case adUnsignedTinyInt
         FieldType = "adUnsignedTinyInt"
      Case adDBTimeStamp
         FieldType = "adDBTimeStamp"
   End Select

End Function


Update and CancelUpdate Methods Example

This example demonstrates the Update method in conjunction with the CancelUpdate method.

Public Sub UpdateX()

   Dim rstEmployees As ADODB.Recordset
   Dim strOldFirst As String
   Dim strOldLast As String
   Dim strMessage As String

   ' Open recordset with names from Employee table.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.CursorType = adOpenKeyset
   rstEmployees.LockType = adLockOptimistic
   rstEmployees.Open "SELECT fname, lname " & _
      "FROM Employee ORDER BY lname", strCnn, , , adCmdText

   ' Store original data.
   strOldFirst = rstEmployees!fname
   strOldLast = rstEmployees!lname
   ' Change data in edit buffer.
   rstEmployees!fname = "Linda"
   rstEmployees!lname = "Kobara"

   ' Show contents of buffer and get user input.
   strMessage = "Edit in progress:" & vbCr & _
      "  Original data = " & strOldFirst & " " & _
      strOldLast & vbCr & "  Data in buffer = " & _
      rstEmployees!fname & " " & rstEmployees!lname & vbCr & vbCr & _
      "Use Update to replace the original data with " & _
      "the buffered data in the Recordset?"

   If MsgBox(strMessage, vbYesNo) = vbYes Then
      rstEmployees.Update
   Else
      rstEmployees.CancelUpdate
   End If

   ' Show the resulting data.
   MsgBox "Data in recordset = " & rstEmployees!fname & " " & _
      rstEmployees!lname

   ' Restore original data because this is a demonstration.
   If Not (strOldFirst = rstEmployees!fname And _
         strOldLast = rstEmployees!lname) Then
      rstEmployees!fname = strOldFirst
      rstEmployees!lname = strOldLast
      rstEmployees.Update
   End If

   rstEmployees.Close

End Sub

This example demonstrates the Update method in conjunction with the AddNew method.

Public Sub UpdateX2()

   Dim cnn1 As ADODB.Connection
   Dim rstEmployees As ADODB.Recordset
   Dim strEmpID As String
   Dim strOldFirst As String
   Dim strOldLast As String
   Dim strMessage As String

   ' Open a connection.
   Set cnn1 = New ADODB.Connection
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   cnn1.Open strCnn

   ' Open recordset with data from Employee table.
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.CursorType = adOpenKeyset
   rstEmployees.LockType = adLockOptimistic
   rstEmployees.Open "employee", cnn1, , , adCmdTable

   rstEmployees.AddNew
   strEmpID = "B-S55555M"
   rstEmployees!emp_id = strEmpID
   rstEmployees!fname = "Bill"
   rstEmployees!lname = "Sornsin"

   ' Show contents of buffer and get user input.
   strMessage = "AddNew in progress:" & vbCr & _
      "Data in buffer = " & rstEmployees!emp_id & ", " & _
      rstEmployees!fname & " " & rstEmployees!lname & vbCr & vbCr & _
      "Use Update to save buffer to recordset?"

   If MsgBox(strMessage, vbYesNoCancel) = vbYes Then
      rstEmployees.Update
      ' Go to the new record and show the resulting data.
      MsgBox "Data in recordset = " & rstEmployees!emp_id & ", " & _
          rstEmployees!fname & " " & rstEmployees!lname
   Else
      rstEmployees.CancelUpdate
      MsgBox "No new record added."
   End If

   ' Delete new data because this is a demonstration.
   cnn1.Execute "DELETE FROM employee WHERE emp_id = '" & strEmpID & "'"

   rstEmployees.Close

End Sub


UpdateBatch and CancelBatch Methods Example

This example demonstrates the UpdateBatch method in conjunction with the CancelBatch method.

Public Sub UpdateBatchX()

   Dim rstTitles As ADODB.Recordset
   Dim strCnn As String
   Dim strTitle As String
   Dim strMessage As String

   ' Assign connection string to variable.
      strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "

   Set rstTitles = New ADODB.Recordset
   rstTitles.CursorType = adOpenKeyset
   rstTitles.LockType = adLockBatchOptimistic
   rstTitles.Open "titles", strCnn, , , adCmdTable

   rstTitles.MoveFirst

   ' Loop through recordset and ask user if she wants
   ' to change the type for a specified title.
   Do Until rstTitles.EOF
      If Trim(rstTitles!Type) = "psychology" Then
         strTitle = rstTitles!Title
         strMessage = "Title: " & strTitle & vbCr & _
            "Change type to self help?"

         If MsgBox(strMessage, vbYesNo) = vbYes Then
            rstTitles!Type = "self_help"
         End If
      End If

      rstTitles.MoveNext
   Loop

   ' Ask if the user wants to commit to all the
   ' changes made above.
   If MsgBox("Save all changes?", vbYesNo) = vbYes Then
      rstTitles.UpdateBatch
   Else
      rstTitles.CancelBatch
   End If

   ' Print current data in recordset.
   rstTitles.Requery
   rstTitles.MoveFirst
   Do While Not rstTitles.EOF
      Debug.Print rstTitles!Title & " - " & rstTitles!Type
      rstTitles.MoveNext
   Loop

   ' Restore original values because this is a demonstration.
   rstTitles.MoveFirst
   Do Until rstTitles.EOF
      If Trim(rstTitles!Type) = "self_help" Then
         rstTitles!Type = "psychology"
      End If
      rstTitles.MoveNext
   Loop
   rstTitles.UpdateBatch

   rstTitles.Close

End Sub


Value Property Example

This example demonstrates the Value property with Field and Property objects by displaying field and property values for the Employees table.

Public Sub ValueX()

   Dim rstEmployees As ADODB.Recordset
   Dim fldLoop As ADODB.Field
   Dim prpLoop As ADODB.Property
   Dim strCnn As String

   ' Open recordset with data from Employee table.
   strCnn = "Provider=sqloledb;" & _
      "Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
   Set rstEmployees = New ADODB.Recordset
   rstEmployees.Open "employee", strCnn, , , adCmdTable

   Debug.Print "Field values in rstEmployees"
   ' Enumerate the Fields collection of the Employees
   ' table.
   For Each fldLoop In rstEmployees.Fields
      ' Because Value is the default property of a
      ' Field object, the use of the actual keyword
      ' here is optional.
      Debug.Print "   " & fldLoop.Name & " = " & fldLoop.Value
   Next fldLoop

   Debug.Print "Property values in rstEmployees"
   ' Enumerate the Properties collection of the
   ' Recordset object.
   For Each prpLoop In rstEmployees.Properties
      ' Because Value is the default property of a
      ' Property object, the use of the actual keyword
      ' here is optional.
      Debug.Print "   " & prpLoop.Name & " = " & prpLoop.Value
   Next prpLoop

   rstEmployees.Close

End Sub


Version Property Example

This example uses the Version property of a Connection object to display the current ADO version. It also uses several dynamic properties to show the current DBMS name and version, OLE DB version, provider name and version, driver name and version, and driver ODBC version.

Public Sub VersionX()

   Dim cnn1 As ADODB.Connection

   ' Open connection.
   Set cnn1 = New ADODB.Connection
   strCnn = “driver={SQL Server};server=srv;” & _
      “user id=sa;password=;database=pubs;”
   cnn1.Open strCnn

   strVersionInfo = "ADO Version: " & cnn1.Version & vbCr & _
   "DBMS Name: " & cnn1.Properties("DBMS Name") & vbCr & _
   "DBMS Version: " & cnn1.Properties("DBMS Version") & vbCr & _
   "OLE DB Version: " & cnn1.Properties("OLE DB Version") & vbCr & _
   "Provider Name: " & cnn1.Properties("Provider Name") & vbCr & _
   "Provider Version: " & cnn1.Properties("Provider Version") & vbCr & _
   "Driver Name: " & cnn1.Properties("Driver Name") & vbCr & _
   "Driver Version: " & cnn1.Properties("Driver Version") & vbCr & _
   "Driver ODBC Version: " & cnn1.Properties("Driver ODBC Version")

   MsgBox strVersionInfo

   cnn1.Close

End Sub


Syntax Index (ADO for VC++)

The ADO Language Reference uses the Microsoft® Visual Basic® programming language to illustrate ADO method and property syntax. This index is a cross-reference to the ADO Language Reference based on Microsoft® Visual C++®.

If you use the #import directive in your application, a header file will be generated that will enable you to use syntax similar to Microsoft Visual Basic. Property names of the form get_PropertyName and put_PropertyName can be treated as if they were declared simply as PropertyName. A property can then be treated like a data member instead of a function.

All of the methods, properties, and events are functions that return an HRESULT, which you can test to determine if the function executed successfully.

Method and property syntax is listed for the following elements:

  • Collections

  • Command object

  • Connection object

  • Error object

  • Field object

  • Parameter object

  • Recordset object


Collections (ADO for VC++ Syntax)

Parameters

Methods

Append(IDispatch *Object)

Delete(VARIANT Index)

get_Item(VARIANT Index, _ADOParameter **ppvObject)

Refresh(void)

Properties

get_Count(long *c)

Fields

Methods

Append(BSTR bstrName, DataTypeEnum Type, long DefinedSize,
FieldAttributeEnum Attrib)

Delete(VARIANT Index)

get_Item(VARIANT Index, ADOField **ppvObject)

Refresh(void)

Properties

get_Count(long *c)

Errors

Methods

Clear(void)

get_Item(VARIANT Index, ADOError **ppvObject)

Refresh(void)

Properties

get_Count(long *c)


_Command (ADO for VC++ Syntax)

Methods

Cancel(void);

CreateParameter(BSTR Name, DataTypeEnum Type,
ParameterDirectionEnum Direction, long Size, VARIANT Value,
_ADOParameter **ppiprm);

Execute(VARIANT *RecordsAffected, VARIANT *Parameters, long Options,
_ADORecordset **ppirs);

Properties

get_ActiveConnection(_ADOConnection **ppvObject);
put_ActiveConnection(VARIANT vConn);
putref_ActiveConnection(_ADOConnection *pCon);

get_CommandText(BSTR *pbstr);
put_CommandText(BSTR bstr);

get_CommandTimeout(LONG *pl);
put_CommandTimeout(LONG Timeout);

get_CommandType(CommandTypeEnum *plCmdType);
put_CommandType(CommandTypeEnum lCmdType);

get_Name(BSTR *pbstrName);
put_Name(BSTR bstrName);

get_Prepared(VARIANT_BOOL *pfPrepared);
put_Prepared(VARIANT_BOOL fPrepared);

get_State(LONG *plObjState);

get_Parameters(ADOParameters **ppvObject);


_Connection (ADO for VC++ Syntax)

Methods

BeginTrans(long *TransactionLevel)
CommitTrans(void)
RollbackTrans(void)

Cancel(void)

Close(void)

Execute(BSTR CommandText, VARIANT *RecordsAffected, long Options,
_ADORecordset **ppiRset)

Open(BSTR ConnectionString, BSTR UserID, BSTR Password, long Options)

OpenSchema(SchemaEnum Schema, VARIANT Restrictions, VARIANT SchemaID,
 _ADORecordset **pprset)

Properties

get_Attributes(long *plAttr)
put_Attributes(long lAttr)

get_CommandTimeout(LONG *plTimeout)
put_CommandTimeout(LONG lTimeout)

get_ConnectionString(BSTR *pbstr)
put_ConnectionString(BSTR bstr)

get_ConnectionTimeout(LONG *plTimeout)
put_ConnectionTimeout(LONG lTimeout)

get_CursorLocation(CursorLocationEnum *plCursorLoc)
put_CursorLocation(CursorLocationEnum lCursorLoc)

get_DefaultDatabase(BSTR *pbstr)
put_DefaultDatabase(BSTR bstr)

get_IsolationLevel(IsolationLevelEnum *Level)
put_IsolationLevel(IsolationLevelEnum Level)

get_Mode(ConnectModeEnum *plMode)
put_Mode(ConnectModeEnum lMode)

get_Provider(BSTR *pbstr)
put_Provider(BSTR Provider)

get_State(LONG *plObjState)

get_Version(BSTR *pbstr)

get_Errors(ADOErrors **ppvObject)

Events

BeginTransComplete(LONG TransactionLevel, ADOError *pError,
EventStatusEnum *adStatus, _ADOConnection *pConnection)

CommitTransComplete(ADOError *pError, EventStatusEnum *adStatus,
_ADOConnection *pConnection)

ConnectComplete(ADOError *pError, EventStatusEnum *adStatus,
_ADOConnection *pConnection)

Disconnect(EventStatusEnum *adStatus, _ADOConnection *pConnection)

ExecuteComplete(LONG RecordsAffected, ADOError *pError,
EventStatusEnum *adStatus, _ADOCommand *pCommand,
_ADORecordset *pRecordset, _ADOConnection *pConnection)

InfoMessage(ADOError *pError, EventStatusEnum *adStatus,
_ADOConnection *pConnection)

RollbackTransComplete(ADOError *pError, EventStatusEnum *adStatus,
_ADOConnection *pConnection)

WillConnect(BSTR *ConnectionString, BSTR *UserID, BSTR *Password,
long *Options, EventStatusEnum *adStatus,
_ADOConnection *pConnection)

WillExecute(BSTR *Source, CursorTypeEnum *CursorType,
LockTypeEnum *LockType, long *Options,
EventStatusEnum *adStatus, _ADOCommand *pCommand,
_ADORecordset *pRecordset, _ADOConnection *pConnection)


Error (ADO for VC++ Syntax)

Properties

get_Description(BSTR *pbstr)

get_NativeError(long *pl)

get_Number(long *pl)

get_Source(BSTR *pbstr)

get_SQLState(BSTR *pbstr)


_Field (ADO for VC++ Syntax)

Methods

AppendChunk(VARIANT Data)

GetChunk(long Length, VARIANT *pvar)

Properties

get_ActualSize(long *pl)

get_Attributes(long *pl)
put_Attributes(long lAttributes)

get_DataFormat(IUnknown **ppiDF)
put_DataFormat(IUnknown *piDF)

get_DefinedSize(long *pl)
put_DefinedSize(long lSize)

get_Name(BSTR *pbstr)

get_NumericScale(BYTE *pbNumericScale)
put_NumericScale(BYTE bScale)

get_OriginalValue(VARIANT *pvar)

get_Precision(BYTE *pbPrecision)
put_Precision(BYTE bPrecision)

get_Type(DataTypeEnum *pDataType)
put_Type(DataTypeEnum DataType)

get_UnderlyingValue(VARIANT *pvar)

get_Value(VARIANT *pvar)
put_Value(VARIANT Val)


_Parameter (ADO for VC++ Syntax)

Methods

AppendChunk(VARIANT Val)

Properties

get_Attributes(LONG *plParmAttribs)
put_Attributes(LONG lParmAttribs)

get_Direction(ParameterDirectionEnum *plParmDirection)
put_Direction(ParameterDirectionEnum lParmDirection)

get_Name(BSTR *pbstr)
put_Name(BSTR bstr)

get_NumericScale(BYTE *pbScale)
put_NumericScale(BYTE bScale)

get_Precision(BYTE *pbPrecision)
put_Precision(BYTE bPrecision)

get_Size(long *pl)
put_Size(long l)

get_Type(DataTypeEnum *psDataType)
put_Type(DataTypeEnum sDataType)

get_Value(VARIANT *pvar)
put_Value(VARIANT val)


_Recordset (ADO for VC++ Syntax)

Methods

AddNew(VARIANT FieldList, VARIANT Values)

Cancel(void)

CancelBatch(AffectEnum AffectRecords)

CancelUpdate(void)

Clone(LockTypeEnum LockType, _ADORecordset **ppvObject)

Close(void)

CompareBookmarks(VARIANT Bookmark1, VARIANT Bookmark2,
CompareEnum *pCompare)

Delete(AffectEnum AffectRecords)

Find(BSTR Criteria, LONG SkipRecords, SearchDirectionEnum SearchDirection,
VARIANT Start)

GetRows(long Rows, VARIANT Start, VARIANT Fields, VARIANT *pvar)

GetString(StringFormatEnum StringFormat, long NumRows, BSTR ColumnDelimeter,
BSTR RowDelimeter, BSTR NullExpr, BSTR *pRetString)

Move(long NumRecords, VARIANT Start)

MoveFirst(void)

MoveLast(void)

MoveNext(void)

MovePrevious(void)

NextRecordset(VARIANT *RecordsAffected, _ADORecordset **ppiRs)

Open(VARIANT Source, VARIANT ActiveConnection, CursorTypeEnum CursorType,
LockTypeEnum LockType, LONG Options)

Requery(LONG Options)

Resync(AffectEnum AffectRecords, ResyncEnum ResyncValues)

Save(BSTR FileName, PersistFormatEnum PersistFormat)

Supports(CursorOptionEnum CursorOptions, VARIANT_BOOL *pb)

Update(VARIANT Fields, VARIANT Values)

UpdateBatch(AffectEnum AffectRecords)

Properties

get_AbsolutePage(PositionEnum *pl)
put_AbsolutePage(PositionEnum Page)

get_AbsolutePosition(PositionEnum *pl)
put_AbsolutePosition(PositionEnum Position)

get_ActiveCommand(IDispatch **ppCmd)

get_ActiveConnection(VARIANT *pvar)
put_ActiveConnection(VARIANT vConn)
putref_ActiveConnection(IDispatch *pconn)

get_BOF(VARIANT_BOOL *pb)

get_Bookmark(VARIANT *pvBookmark)
put_Bookmark(VARIANT vBookmark)

get_CacheSize(long *pl)
put_CacheSize(long CacheSize)

get_CursorLocation(CursorLocationEnum *plCursorLoc)
put_CursorLocation(CursorLocationEnum lCursorLoc)

get_CursorType(CursorTypeEnum *plCursorType)
put_CursorType(CursorTypeEnum lCursorType)

get_DataMember(BSTR *pbstrDataMember)
put_DataMember(BSTR bstrDataMember)

get_DataSource(IUnknown **ppunkDataSource)
putref_DataSource(IUnknown *punkDataSource)

get_EditMode(EditModeEnum *pl)

get_EOF(VARIANT_BOOL *pb)

get_Filter(VARIANT *Criteria)
put_Filter(VARIANT Criteria)

get_LockType(LockTypeEnum *plLockType)
put_LockType(LockTypeEnum lLockType)

get_MarshalOptions(MarshalOptionsEnum *peMarshal)
put_MarshalOptions(MarshalOptionsEnum eMarshal)

get_MaxRecords(long *plMaxRecords)
put_MaxRecords(long lMaxRecords)

get_PageCount(long *pl)

get_PageSize(long *pl)
put_PageSize(long PageSize)

get_RecordCount(long *pl)

get_Sort(BSTR *Criteria)
put_Sort(BSTR Criteria)

get_Source(VARIANT *pvSource)
put_Source(BSTR bstrConn)
putref_Source(IDispatch *pcmd)

get_State(LONG *plObjState)

get_Status(long *pl)

get_StayInSync(VARIANT_BOOL *pbStayInSync)
put_StayInSync(VARIANT_BOOL bStayInSync)

get_Fields(ADOFields **ppvObject)

Miscellaneous

get_Collect(VARIANT Index, VARIANT *pvar)
put_Collect(VARIANT Index, VARIANT value)

Events

EndOfRecordset(VARIANT_BOOL *fMoreData, EventStatusEnum *adStatus,
_ADORecordset *pRecordset)

FetchComplete(ADOError *pError, EventStatusEnum *adStatus,
_ADORecordset *pRecordset)

FetchProgress(long Progress, long MaxProgress, EventStatusEnum *adStatus,
_ADORecordset *pRecordset)

FieldChangeComplete(LONG cFields, VARIANT Fields, ADOError *pError,
EventStatusEnum *adStatus, _ADORecordset *pRecordset)

MoveComplete(EventReasonEnum adReason, ADOError *pError,
EventStatusEnum *adStatus, _ADORecordset *pRecordset)

RecordChangeComplete(EventReasonEnum adReason, LONG cRecords,
ADOError *pError, EventStatusEnum *adStatus,
_ADORecordset *pRecordset)

RecordsetChangeComplete(EventReasonEnum adReason, ADOError *pError,
EventStatusEnum *adStatus, _ADORecordset *pRecordset)

WillChangeField(LONG cFields, VARIANT Fields, EventStatusEnum *adStatus,
_ADORecordset *pRecordset)

WillChangeRecord(EventReasonEnum adReason, LONG cRecords,
EventStatusEnum *adStatus, _ADORecordset *pRecordset)

WillChangeRecordset(EventReasonEnum adReason, EventStatusEnum *adStatus,
_ADORecordset *pRecordset)

WillMove(EventReasonEnum adReason, EventStatusEnum *adStatus,
_ADORecordset *pRecordset)


Syntax Index (ADO/WFC)

The ADO Language Reference uses the Microsoft® Visual Basic® programming language to illustrate ADO method and property syntax. This index is a cross-reference to the ADO Language Reference topics based on Microsoft® Visual J++™ and ADO for Windows Foundation Classes (ADO/WFC). When differences in syntax arise, use the function signatures in this index as opposed to the syntax listings in the language reference topic.

Method and property syntax is listed for the following elements:

ActiveX Data Objects

  • Collections (Parameters, Fields, Errors)

  • Command object

  • Connection object

  • Error object

  • Field object

  • Parameter object

  • Recordset object

Remote Data Service

  • DataSpace

  • ObjectProxy


Collections (ADO/WFC Syntax)

package com.ms.wfc.data

Parameters

Methods

public void append(com.ms.wfc.data.Parameter param)

public void delete(int n)
public void delete(String s)

public void refresh()

public Parameter getItem(int n)
public Parameter getItem(String s)

Properties

public int getCount()

Fields

Methods

public void append(String name, int type)
public void append(String name, int type, int definedSize)
public void append(String name, int type, int definedSize, int attrib)

public void delete(int n)
public void delete(String s)

public void refresh()

public com.ms.wfc.data.Field getItem(int n)
public com.ms.wfc.data.Field getItem(String s)

Properties

public int getCount()

Errors

Methods

public void clear()

public void refresh()

public com.ms.wfc.data.Error getItem(int n)
public com.ms.wfc.data.Error getItem(String s)

Properties

public int getCount()


Command (ADO/WFC Syntax)

package com.ms.wfc.data

Constructor

public Command()
public Command(String commandtext)

Methods

public void cancel()

public com.ms.wfc.data.Parameter createParameter(String Name, int Type, int Direction, int Size, Object Value)

public Recordset execute()
public Recordset execute(Object[] parameters)
public Recordset execute(Object[] parameters, int options)

public int executeUpdate(Object[] parameters)
public int executeUpdate(Object[] parameters, int options)
public int executeUpdate()

Properties

public com.ms.wfc.data.Connection getActiveConnection()
public void setActiveConnection(com.ms.wfc.data.Connection con)
public void setActiveConnection(String conString)

public String getCommandText()
public void setCommandText(String command)

public int getCommandTimeout()
public void setCommandTimeout(int timeout)

public int getCommandType()
public void setCommandType(int type)

public String getName()
public void setName(String name)

public boolean getPrepared()
public void setPrepared(boolean prepared)

public int getState()

public com.ms.wfc.data.Parameter getParameter(int n)
public com.ms.wfc.data.Parameter getParameter(String n)

public com.ms.wfc.data.Parameters getParameters()

public AdoProperties getProperties()


Connection (ADO/WFC Syntax)

package com.ms.wfc.data

Constructor

public Connection()
public Connection(String connectionstring)

Methods

public int beginTrans()
public void commitTrans()
public void rollbackTrans()

public void cancel()

public void close()

public com.ms.wfc.data.Recordset execute(String commandText)
public com.ms.wfc.data.Recordset execute(String commandText, int options)

public int executeUpdate(String commandText)
public int executeUpdate(String commandText, int options)

public void open()
public void open(String connectionString)
public void open(String connectionString, String userID)
public void open(String connectionString, String userID, String password)
public void open(String connectionString, String userID, String password, int options)

public Recordset openSchema(int schema, Object[] restrictions, String schemaID)
public Recordset openSchema(int schema)
public Recordset openSchema(int schema, Object[] restrictions)

Properties

public int getAttributes()
public void setAttributes(int attr)

public int getCommandTimeout()
public void setCommandTimeout(int timeout)

public String getConnectionString()
public void setConnectionString(String con)

public int getConnectionTimeout()
public void setConnectionTimeout(int timeout)

public int getCursorLocation()
public void setCursorLocation(int cursorLoc)

public String getDefaultDatabase()
public void setDefaultDatabase(String db)

public int getIsolationLevel()
public void setIsolationLevel(int level)

public int getMode()
public void setMode(int mode)

public String getProvider()
public void setProvider(String provider)

public int getState()

public String getVersion()

public AdoProperties getProperties()

public com.ms.wfc.data.Errors getErrors()

Events

For more information about ADO/WFC events, see ADO Events in ADO/WFC.

public void addOnBeginTransComplete(ConnectionEventHandler handler)
public void removeOnBeginTransComplete(ConnectionEventHandler handler)

public void addOnCommitTransComplete(ConnectionEventHandler handler)
public void removeOnCommitTransComplete(ConnectionEventHandler handler)

public void addOnConnectComplete(ConnectionEventHandler handler)
public void removeOnConnectComplete(ConnectionEventHandler handler)

public void addOnDisconnect(ConnectionEventHandler handler)
public void removeOnDisconnect(ConnectionEventHandler handler)

public void addOnExecuteComplete(ConnectionEventHandler handler)
public void removeOnExecuteComplete(ConnectionEventHandler handler)

public void addOnInfoMessage(ConnectionEventHandler handler)
public void removeOnInfoMessage(ConnectionEventHandler handler)

public void addOnRollbackTransComplete(ConnectionEventHandler handler)
public void removeOnRollbackTransComplete(ConnectionEventHandler handler)

public void addOnWillConnect(ConnectionEventHandler handler)
public void removeOnWillConnect(ConnectionEventHandler handler)

public void addOnWillExecute(ConnectionEventHandler handler)
public void removeOnWillExecute(ConnectionEventHandler handler)


DataSpace (ADO/WFC Syntax)

The ADO/WFC DataSpace class has one method, createObject, which specifies a server and communication protocol; a server object to process client application requests; and returns an ObjectProxy object that represents the server.

package com.ms.wfc.data

Constructor

public DataSpace()

Methods

public static ObjectProxy DataSpace. createObject(String progid, String connection)

Properties

public static int getInternetTimeout()
public static void setInternetTimeout(int plInetTimeout)


Error (ADO/WFC Syntax)

package com.ms.wfc.data

Properties

public String getDescription()

public int getNativeError()

public int getNumber()

public String getSource()

public String getSQLState()


Field (ADO/WFC Syntax)

package com.ms.wfc.data

Methods

public void appendChunk(byte[] bytes)
public void appendChunk(char[] chars)
public void appendChunk(String chars)

public byte[] getByteChunk(int len)
public char[] getCharChunk(int len)
public String getStringChunk(int len)

Properties

public int getActualSize()

public int getAttributes()
public void setAttributes(int pl)

public com.ms.com.IUnknown getDataFormat()
public void setDataFormat(com.ms.com.IUnknown format)
(For more information, see the Microsoft Visual J++ WFC Reference documentation for the com.ms.wfc.data.IDataFormat interface.)

public int getDefinedSize()
public void setDefinedSize(int pl)

public String getName()

public int getNumericScale()
public void setNumericScale(byte pbNumericScale)

public Variant getOriginalValue()

public int getPrecision()
public void setPrecision(byte pbPrecision)

public int getType()
public void setType(int pDataType)

public Variant getUnderlyingValue()

public Variant getValue()
public void setValue(Variant value)

public AdoProperties getProperties()

Field Accessor Methods

The Value property of a Field object gets or sets the content of that object. The content is represented as a VARIANT, a type of object that can be assigned a value and any of several data types.

ADO/WFC implements the Value property with the getValue method, which returns a VARIANT object; and the setValue method, which takes a VARIANT as an argument. VARIANTs are highly efficient in certain languages, such as Microsoft Visual Basic. However, you can attain better performance in Microsoft Visual J++ by using native Java data types.

In addition to the Value property, ADO/WFC provides accessor methods that use Java data types to get and set the content of Field objects. Most of these methods have names of the form get DataType or set DataType.

There are two noteworthy exceptions: One of the getObject methods returns an object coerced to a specified class. There is no getNull property; instead, there is an isNull property that returns a Boolean value indicating whether the field is null.

public native boolean getBoolean();
public void setBoolean(boolean v)

public native byte getByte();
public void setByte(byte v)

public native byte[] getBytes();
public void setBytes(byte[] v)

public native double getDouble();
public void setDouble(double v)

public native float getFloat();
public void setFloat(float v)

public native int getInt();
public void setInt(int v)

public native long getLong();
public void setLong(long v)

public native short getShort();
public void setShort(short v)

public native String getString();
public void setString(String v)

public native boolean isNull();
public void setNull()

public Object getObject()
public Object getObject(Class c)
public void setObject(Object value)


ObjectProxy (ADO/WFC Syntax)

An ObjectProxy object represents a server, and is returned by the createObject method of the DataSpace object. The ObjectProxy class has one method, call, which can invoke a method on the server and return an object resulting from that invocation.

package com.ms.wfc.data

Methods

Call Method (ADO/WFC Syntax)

Invokes a method on the server represented by the ObjectProxy. Optionally, method arguments may be passed as an array of objects.

Syntax

public Object ObjectProxy.call( String method )
public Object ObjectProxy.call( String method, Object[] args)

Returns

Object An object resulting from invoking the method.

Parameters

ObjectProxy An ObjectProxy object that represents the server.

method A String, containing the name of the method to invoke on the server.

args Optional. An array of objects which are arguments to the method on the server. Java data types are automatically converted to data types suitable for use on the server.


Parameter (ADO/WFC Syntax)

package com.ms.wfc.data

Constructor

public Parameter()
public Parameter(String name)
public Parameter(String name, int type)
public Parameter(String name, int type, int dir)
public Parameter(String name, int type, int dir, int size)
public Parameter(String name, int type, int dir, int size, Object value)

Methods

public void appendChunk(byte[] bytes)
public void appendChunk(char[] chars)
public void appendChunk(String chars)

Properties

public int getAttributes()
public void setAttributes(int attr)

public int getDirection()
public void setDirection(int dir)

public String getName()
public void setName(String name)

public int getNumericScale()
public void setNumericScale(int scale)

public int getPrecision()
public void setPrecision(int prec)

public int getSize()
public void setSize(int size)

public int getType()
public void setType(int type)

public com.ms.com.Variant getValue()
public void setValue(Object v)

public AdoProperties getProperties()

Parameter Accessor Methods

The Value property of a Parameter object gets or sets the content of that object. The content is represented as a VARIANT, a type of object that can be assigned a value and any of several data types.

ADO/WFC implements the Value property with the getValue method, which returns a VARIANT object; and the setValue method, which takes a VARIANT as an argument. VARIANTs are highly efficient in certain languages, such as Microsoft Visual Basic. However, you can attain better performance in Microsoft Visual J++ by using native Java data types.

In addition to the Value property, ADO/WFC provides accessor methods that use Java data types to get and set the content of Parameter objects. Most of these methods have names of the form get DataType or set DataType.

There is one noteworthy exception: There is no getNull property; instead, there is an isNull property that returns a Boolean value indicating whether the field is null.

public boolean getBoolean()
public void setBoolean(boolean v)

public byte getByte()
public void setByte(byte v)

public double getDouble()
public void setDouble(double v)

public float getFloat()
public void setFloat(float v)

public int getInt()
public void setInt(int v)

public long getLong()
public void setLong(long v)

public short getShort()
public void setShort(short v)

public String getString()
public void setString(String v)

public boolean isNull()
public void setNull()


Recordset (ADO/WFC Syntax)

package com.ms.wfc.data

Constructors

public Recordset()
public Recordset(Object r)

Methods

public void addNew(Object[] fieldList, Object[] valueList)
public void addNew(Object[] valueList)
public void addNew()

public void cancel()

public void cancelBatch(int affectRecords)
public void cancelBatch()

public void cancelUpdate()

public Object clone()
public Object clone(int lockType)

public void close()

public int compareBookmarks(Object bookmark1, Object bookmark2)

public void delete(int affectRecords)
public void delete()

public void find(String criteria)
public void find(String criteria, int SkipRecords)
public void find(String criteria, int SkipRecords, int searchDirection)
public void find(String criteria, int SkipRecords, int searchDirection, Object bmkStart)

public Object[][] getRows(int Rows, Object bmkStart, Object[] fieldList)

public void move(int numRecords)
public void move(int numRecords, Object bmkStart)

public void moveFirst()
public void moveLast()
public void moveNext()
public void movePrevious()

public Recordset nextRecordset()
public Recordset nextRecordset(int[] recordsAffected)

public void open()
public void open(Object source)
public void open(Object source, Object activeConnection)
public void open(Object source, Object activeConnection, int cursorType)
public void open(Object source, Object activeConnection, int cursorType,
int lockType)
public void open(Object source, Object activeConnection, int cursorType,
int lockType, int options)

public void requery()
public void requery(int options)

public void resync()
public void resync(int affectRecords, int resyncValues)

public void save(String fileName)
public void save(String fileName, int persistFormat)

public boolean supports(int cursorOptions)

public void update()
public void update(Object[] valueList)
public void update(Object[] fieldList, Object[] valueList)

public void updateBatch()
public void updateBatch(int affectRecords)

Properties

public int getAbsolutePage()
public void setAbsolutePage(int page)

public int getAbsolutePosition()
public void setAbsolutePosition(int pos)

public Command getActiveCommand()

public Connection getActiveConnection()
public void setActiveConnection(String conn)
public void setActiveConnection(com.ms.wfc.data.Connection c)

public boolean getBOF()

public boolean getEOF()

public Object getBookmark()
public void setBookmark(Object bmk)

public int getCacheSize()
public void setCacheSize(int size)

public int getCursorLocation()
public void setCursorLocation(int cursorLoc)

public int getCursorType()
public void setCursorType(int cursorType)

public String getDataMember()
public void setDataMember(String pbstrDataMember)

public Iunknown getDataSource()
public void setDataSource(IUnknown dataSource)

public int getEditMode()

public Object getFilter()
public void setFilter(Object filter)

public int getLockType()
public void setLockType(int lockType)

public int getMarshalOptions()
public void setMarshalOptions(int options)

public int getMaxRecords()
public void setMaxRecords(int maxRecords)

public int getPageCount()

public int getPageSize()
public void setPageSize(int pageSize)

public int getRecordCount()

public String getSort()
public void setSort(String criteria)

public String getSource()
public void setSource(String query)
public void setSource(com.ms.wfc.data.Command command)

public int getState()

public int getStatus()

public boolean getStayInSync()
public void setStayInSync(boolean pbStayInSync)

public com.ms.wfc.data.Field getField(int n)
public com.ms.wfc.data.Field getField(String n)

public com.ms.wfc.data.Fields getFields()

public AdoProperties getProperties()

Events

For more information about ADO/WFC events, see ADO Events in ADO/WFC.

public void addOnEndOfRecordset(RecordsetEventHandler handler)
public void removeOnEndOfRecordset(RecordsetEventHandler handler)

public void addOnFetchComplete(RecordsetEventHandler handler)
public void removeOnFetchComplete(RecordsetEventHandler handler)

public void addOnFetchProgress(RecordsetEventHandler handler)
public void removeOnFetchProgress(RecordsetEventHandler handler)

public void addOnFieldChangeComplete(RecordsetEventHandler handler)
public void removeOnFieldChangeComplete(RecordsetEventHandler handler)

public void addOnMoveComplete(RecordsetEventHandler handler)
public void removeOnMoveComplete(RecordsetEventHandler handler)

public void addOnRecordChangeComplete(RecordsetEventHandler handler)
public void removeOnRecordChangeComplete(RecordsetEventHandler handler)

public void addOnRecordsetChangeComplete(RecordsetEventHandler handler)
public void removeOnRecordsetChangeComplete(RecordsetEventHandler handler)

public void addOnWillChangeField(RecordsetEventHandler handler)
public void removeOnWillChangeField(RecordsetEventHandler handler)

public void addOnWillChangeRecord(RecordsetEventHandler handler)
public void removeOnWillChangeRecord(RecordsetEventHandler handler)

public void addOnWillChangeRecordset(RecordsetEventHandler handler)
public void removeOnWillChangeRecordset(RecordsetEventHandler handler)

public void addOnWillMove(RecordsetEventHandler handler)
public void removeOnWillMove(RecordsetEventHandler handler)


AdoEnums (ADO/WFC Syntax)

To use AdoEnums, specify the fully qualified name of the enumerated constant. For example, the first constant in the AdoEnums.Schema class is AdoEnums.Schema.PROVIDERSPECIFIC.

Each topic lists the values of the constants. However, use the constant names, not the values. The values are subject to change between releases.

The tables that follow contain three headings that pertain to the core ADO documentation.

  • Topic This heading is a link to the ADO documentation topic where the enumerated constant is described.

  • Prefix The names of the ADO/WFC enumerated constants are derived from their ADO counterparts. However, when you read the ADO documentation, it may not be obvious which is the corresponding ADO constant.

    The last qualifier in the ADO/WFC constant is an identifier, written in upper-case. The ADO constant consists of a prefix, followed by the identifier written in mixed-case.

    For example, the equivalent of the ADO/WFC constant, AdoEnums.Schema.PROVIDERSPECIFIC, is the ADO constant, adSchemaProviderSpecific. In this case the prefix, adSchema, is prepended to the identifier, ProviderSpecific.

    This heading lists the prefix you should append to the ADO/WFC identifier to generate the name of the ADO enumerated constant.

  • Declared ADO COM interface files declare each set of enumerated constants. This heading shows the name of that declaration.

    The name of the COM declaration can be derived from the ADO/WFC constant by suffixing Enum to the second qualifier. For example, the COM declaration associated with AdoEnums.Schema.* is named SchemaEnum.

The following enumerations are defined in ADO/WFC.

AdcPropAsyncThreadPriority | DataType | ObjectState
AdcPropUpdateCriteria | EditMode | ParameterAttributes
Affect | ErrorValue | ParameterDirection
Bookmark | EventReason | PersistFormat
CommandType | EventStatus | Position
Compare | ExecuteOption | PropertyAttributes
ConnectMode | FieldAttribute | RecordStatus
ConnectOption | FilterGroup | Resync
ConnectPrompt | GetRowsOption | Schema
CursorLocation | IsolationLevel | SearchDirection
CursorOption | LockType | StringFormat
CursorType | MarshalOptions | XactAttribute


AdoEnums.AdcPropAsyncThreadPriority.*

package com.ms.wfc.data

Topic For an RDS Recordset object, specifies the execution priority of the asynchronous thread that fetches data. Use these constants with the recordset "Background Thread Priority" dynamic property.

Prefix adPriority

Declared ADCPROP_ASYNCTHREADPRIORITY_ENUM

Constant | Value
LOWEST | 1
BELOWNORMAL | 2
NORMAL | 3
ABOVENORMAL | 4
HIGHEST | 5


AdoEnums.AdcPropUpdateCriteria.*

package com.ms.wfc.data

Topic Specifies which fields can be used to detect conflicts during an optimistic update of a row of the data source with an RDS Recordset object. The constants specify that collisions should be detected if there is a change to the key field (that is, the data source row has been deleted); a change to any column in the data source row; a change to the same column of the data source row as the updated column of the recordset; or if the data source row has merely been accessed. Use these constants with the recordset "Update Criteria" dynamic property.

Prefix adCriteria

Declared ADCPROP_UPDATECRITERIA_ENUM

Constant | Value
KEY | 0
ALLCOLS | 1
UPDCOLS | 2
TIMESTAMP | 3


AdoEnums.Affect.*

package com.ms.wfc.data

Topic UpdateBatch Method

Prefix adAffect

Declared AffectEnum

Constant | Value
CURRENT | 1
GROUP | 2
ALL | 3
ALLCHAPTERS | 4


AdoEnums.Bookmark.*

package com.ms.wfc.data

Topic Find, GetRows, Move Methods

Prefix adBookmark

Declared BookmarkEnum

Constant | Value
CURRENT | 0
FIRST | 1
LAST | 2


AdoEnums.CommandType.*

package com.ms.wfc.data

Topic CommandType Property

Prefix adCmd

Declared CommandTypeEnum

Constant | Value
UNSPECIFIED | -1
UNKNOWN | 8
TEXT | 1
TABLE | 2
STOREDPROC | 4
FILE | 256
TABLEDIRECT | 512


AdoEnums.Compare.*

package com.ms.wfc.data

Topic CompareBookmarks Method

Prefix adCompare

Declared CompareEnum

Constant | Value
LESSTHAN | 0
EQUAL | 1
GREATERTHAN | 2
NOTEQUAL | 3
NOTCOMPARABLE | 4


AdoEnums.ConnectMode.*

package com.ms.wfc.data

Topic Mode Property

Prefix adMode

Declared ConnectModeEnum

Constant | Value
UNKNOWN | 0
READ | 1
WRITE | 2
READWRITE | 3
SHAREDENYREAD | 4
SHAREDENYWRITE | 8
SHAREEXCLUSIVE | 12
SHAREDENYNONE | 16


AdoEnums.ConnectOption.*

package com.ms.wfc.data

Topic Connect.Open Method (referred to as OpenOptionEnum)

Prefix ad

Declared ConnectOptionEnum

Constant | Value
CONNECTUNSPECIFIED | -1
ASYNCCONNECT | 16


AdoEnums.ConnectPrompt.*

package com.ms.wfc.data

Topic Specifies whether a dialog box should be displayed to prompt for missing parameters when opening a connection to an ODBC data source. The constants specify whether to always prompt, prompt if more information is needed, prompt if more information is needed but optional parameters are not allowed, or never prompt. Use these constants with the connection "Prompt" dynamic property.

Prefix adPrompt

Declared ConnectPromptEnum

Constant | Value
ALWAYS | 1
COMPLETE | 2
COMPLETEREQUIRED | 3
NEVER | 4


AdoEnums.CursorLocation.*

package com.ms.wfc.data

Topic CursorLocation Property

Prefix adUse

Declared CursorLocationEnum

Constant | Value
NONE | 1
SERVER | 2
CLIENT | 3


AdoEnums.CursorOption.*

package com.ms.wfc.data

Topic Supports Method

Prefix ad

Declared CursorOptionEnum

Constant | Value
HOLDRECORDS | 256
MOVEPREVIOUS | 512
ADDNEW | 16778240
DELETE | 16779264
UPDATE | 16809984
BOOKMARK | 8192
APPROXPOSITION | 16384
UPDATEBATCH | 65536
RESYNC | 131072
NOTIFY | 262144
FIND | 524288


AdoEnums.CursorType.*

package com.ms.wfc.data

Topic CursorType Property

Prefix adOpen

Declared CursorTypeEnum

Constant | Value
UNSPECIFIED | -1
FORWARDONLY | 0
KEYSET | 1
DYNAMIC | 2
STATIC | 3


AdoEnums.DataType.*

package com.ms.wfc.data

Topic Append Method

Prefix ad

Declared DataTypeEnum

Constant | Value | Constant | Value | Constant | Value
EMPTY | 0 | DECIMAL | 14 | DBTIMESTAMP | 135
TINYINT | 16 | NUMERIC | 131 | BSTR | 8
SMALLINT | 2 | BOOLEAN | 11 | CHAR | 129
INTEGER | 3 | ERROR | 10 | VARCHAR | 200
BIGINT | 20 | USERDEFINED | 132 | LONGVARCHAR | 201
UNSIGNEDTINYINT | 17 | VARIANT | 12 | WCHAR | 130
UNSIGNEDSMALLINT | 18 | IDISPATCH | 9 | VARWCHAR | 202
UNSIGNEDINT | 19 | IUNKNOWN | 13 | LONGVARWCHAR | 203
UNSIGNEDBIGINT | 21 | GUID | 72 | BINARY | 128
SINGLE | 4 | DATE | 7 | VARBINARY | 204
DOUBLE | 5 | DBDATE | 133 | LONGVARBINARY | 205
CURRENCY | 6 | DBTIME | 134 | CHAPTER | 136


AdoEnums.EditMode.*

package com.ms.wfc.data

Topic EditMode Property

Prefix adEdit

Declared EditModeEnum

Constant | Value
NONE | 0
INPROGRESS | 1
ADD | 2
DELETE | 4


AdoEnums.ErrorValue.*

package com.ms.wfc.data

Topic ADO Error Codes

Prefix adErr

Declared ErrorValueEnum

Constant | Value | Constant | Value
INVALIDARGUMENT | 3001 | OBJECTOPEN | 3705
NOCURRENTRECORD | 3021 | PROVIDERNOTFOUND | 3706
ILLEGALOPERATION | 3219 | BOUNDTOCOMMAND | 3707
INTRANSACTION | 3246 | INVALIDPARAMINFO | 3708
FEATURENOTAVAILABLE | 3251 | INVALIDCONNECTION | 3709
ITEMNOTFOUND | 3265 | NOTREENTRANT | 3710
OBJECTINCOLLECTION | 3367 | STILLEXECUTING | 3711
OBJECTNOTSET | 3420 | OPERATIONCANCELLED | 3712
DATACONVERSION | 3421 | STILLCONNECTING | 3713
OBJECTCLOSED | 3704 | NOTEXECUTING | 3715
 |  | UNSAFEOPERATION | 3716


AdoEnums.EventReason.*

package com.ms.wfc.data

Topic WillMove, WillChangeRecord, WillChangeRecordset Methods

Prefix adRsn

Declared EventReasonEnum

Constant | Value | Constant | Value
ADDNEW | 1 | CLOSE | 9
DELETE | 2 | MOVE | 10
UPDATE | 3 | FIRSTCHANGE | 11
UNDOUPDATE | 4 | MOVEFIRST | 12
UNDOADDNEW | 5 | MOVENEXT | 13
UNDODELETE | 6 | MOVEPREVIOUS | 14
REQUERY | 7 | MOVELAST | 15
RESYNCH | 8 |  |


AdoEnums.EventStatus.*

package com.ms.wfc.data

Topic All ADO Events

Prefix adStatus

Declared EventStatusEnum

Constant | Value
OK | 1
ERRORSOCCURRED | 2
CANTDENY | 3
CANCEL | 4
UNWANTEDEVENT | 5


AdoEnums.ExecuteOption.*

package com.ms.wfc.data

Topic Execute Method

Prefix ad

Declared ExecuteOptionEnum

Constant | Value
UNSPECIFIED | -1
ASYNCEXECUTE | 16
ASYNCFETCH | 32
ASYNCFETCHNONBLOCKING | 64


AdoEnums.FieldAttribute.*

package com.ms.wfc.data

Topic Attribute Property

Prefix adFld

Declared FieldAttributeEnum

Constant | Value
UNSPECIFIED | -1
MAYDEFER | 2
UPDATABLE | 4
UNKNOWNUPDATABLE | 8
FIXED | 16
ISNULLABLE | 32
MAYBENULL | 64
LONG | 128
ROWID | 256
ROWVERSION | 512
CACHEDEFERRED | 4096


AdoEnums.FilterGroup.*

package com.ms.wfc.data

Topic Filter Property

Prefix adFilter

Declared FilterGroupEnum

Constant | Value
NONE | 0
PENDINGRECORDS | 1
AFFECTEDRECORDS | 2
FETCHEDRECORDS | 3
PREDICATE | 4
CONFLICTINGRECORDS | 5


AdoEnums.GetRowsOption.*

package com.ms.wfc.data

Topic GetRows Method

Prefix adGetRows

Declared GetRowsOptionEnum

Constant | Value
REST | -1


AdoEnums.IsolationLevel.*

package com.ms.wfc.data

Topic IsolationLevel Property

Prefix adXact

Declared IsolationLevelEnum

Constant | Value
UNSPECIFIED | -1
CHAOS | 16
READUNCOMMITTED | 256
BROWSE | 256
CURSORSTABILITY | 4096
READCOMMITTED | 4096
REPEATABLEREAD | 65536
SERIALIZABLE | 1048576
ISOLATED | 1048576


AdoEnums.LockType.*

package com.ms.wfc.data

Topic LockType Property

Prefix adLock

Declared LockTypeEnum

Constant | Value
UNSPECIFIED | -1
READONLY | 1
PESSIMISTIC | 2
OPTIMISTIC | 3
BATCHOPTIMISTIC | 4


AdoEnums.MarshalOptions.*

package com.ms.wfc.data

Topic MarshalOptions Property

Prefix adMarshal

Declared MarshalOptionsEnum

Constant | Value
ALL | 0
MODIFIEDONLY | 1


AdoEnums.ObjectState.*

package com.ms.wfc.data

Topic State Property

Prefix adState

Declared ObjectStateEnum

Constant | Value
CLOSED | 0
OPEN | 1
CONNECTING | 2
EXECUTING | 4
FETCHING | 8


AdoEnums.ParameterAttributes.*

package com.ms.wfc.data

Topic Attribute Property

Prefix adParam

Declared ParameterAttributesEnum

Constant | Value
SIGNED | 16
NULLABLE | 64
LONG | 128


AdoEnums.ParameterDirection.*

package com.ms.wfc.data

Topic Direction Property

Prefix adParam

Declared ParameterDirectionEnum

Constant | Value
UNKNOWN | 0
INPUT | 1
OUTPUT | 2
INPUTOUTPUT | 3
RETURNVALUE | 4


AdoEnums.PersistFormat.*

package com.ms.wfc.data

Topic Save Method

Prefix adPersist

Declared PersistFormatEnum

Constant | Value
ADTG | 0
XML | 1


AdoEnums.Position.*

package com.ms.wfc.data

Topic AbsolutePage and AbsolutePosition Properties

Prefix adPos

Declared PositionEnum

Constant | Value
UNKNOWN | -1
BOF | -2
EOF | -3


AdoEnums.PropertyAttributes.*

package com.ms.wfc.data

Topic Attribute Property

Prefix adProp

Declared PropertyAttributesEnum

Constant | Value
NOTSUPPORTED | 0
REQUIRED | 1
OPTIONAL | 2
READ | 512
WRITE | 1024


AdoEnums.RecordStatus.*

package com.ms.wfc.data

Topic Status Property

Prefix adRec

Declared RecordStatusEnum

Constant | Value | Constant | Value
OK | 0 | CANTRELEASE | 1024
NEW | 1 | CONCURRENCYVIOLATION | 2048
MODIFIED | 2 | INTEGRITYVIOLATION | 4096
DELETED | 4 | MAXCHANGESEXCEEDED | 8192
UNMODIFIED | 8 | OBJECTOPEN | 16384
INVALID | 16 | OUTOFMEMORY | 32768
MULTIPLECHANGES | 64 | PERMISSIONDENIED | 65536
PENDINGCHANGES | 128 | SCHEMAVIOLATION | 131072
CANCELED | 256 | DBDELETED | 262144


AdoEnums.Resync.*

package com.ms.wfc.data

Topic Resync Method

Prefix adResync

Declared ResyncEnum

Constant | Value
UNDERLYINGVALUES | 1
ALLVALUES | 2


AdoEnums.Schema.*

package com.ms.wfc.data

Topic OpenSchema Method

Prefix adSchema

Declared SchemaEnum

Constant | Value | Constant | Value
PROVIDERSPECIFIC | -1 | STATISTICS | 19
ASSERTS | 0 | TABLES | 20
CATALOGS | 1 | TRANSLATIONS | 21
CHARACTERSETS | 2 | PROVIDERTYPES | 22
COLLATIONS | 3 | VIEWS | 23
COLUMNS | 4 | VIEWCOLUMNUSAGE | 24
CHECKCONSTRAINTS | 5 | VIEWTABLEUSAGE | 25
CONSTRAINTCOLUMNUSAGE | 6 | PROCEDUREPARAMETERS | 26
CONSTRAINTTABLEUSAGE | 7 | FOREIGNKEYS | 27
KEYCOLUMNUSAGE | 8 | PRIMARYKEYS | 28
REFERENTIALCONTRAINTS | 9 | PROCEDURECOLUMNS | 29
TABLECONSTRAINTS | 10 | DBINFOKEYWORDS | 30
COLUMNSDOMAINUSAGE | 11 | DBINFOLITERALS | 31
INDEXES | 12 | CUBES | 32
COLUMNPRIVILEGES | 13 | DIMENSIONS | 33
TABLEPRIVILEGES | 14 | HIERARCHIES | 34
USAGEPRIVILEGES | 15 | LEVELS | 35
PROCEDURES | 16 | MEASURES | 36
SCHEMATA | 17 | PROPERTIES | 37
SQLLANGUAGES | 18 | MEMBERS | 38


AdoEnums.SearchDirection.*

package com.ms.wfc.data

Topic Find Method

Prefix adSearch

Declared SearchDirectionEnum

Constant | Value
FORWARD | 1
BACKWARD | -1


AdoEnums.StringFormat.*

package com.ms.wfc.data

Topic GetString Method

Prefix ad

Declared StringFormatEnum

Constant | Value
CLIPSTRING | 2


AdoEnums.XactAttribute.*

package com.ms.wfc.data

Topic Attribute Property

Prefix adXact

Declared XactAttributeEnum

Constant | Value
COMMITRETAINING | 131072
ABORTRETAINING | 262144
ASYNCPHASEONE | 524288
SYNCPHASEONE | 1048576


ADO Error Codes

In addition to the provider errors that are described in the Error object and Errors collection, ADO itself can return errors to the exception-handling mechanism of your run-time environment. Use your programming language's error trapping mechanism, such as the On Error statement in Microsoft® Visual Basic®, to trap and handle the following errors. Both decimal and hexadecimal error code values are shown.

Constant name | Number | Description
adErrInvalidArgument | 3001 0x800A0BB9 | The application is using arguments that are of the wrong type, are out of acceptable range, or are in conflict with one another.
adErrNoCurrentRecord | 3021 0x800A0BCD | Either BOF or EOF is True, or the current record has been deleted; the operation requested by the application requires a current record.
adErrIllegalOperation | 3219 0x800A0C93 | The operation requested by the application is not allowed in this context.
adErrInTransaction | 3246 0x800A0CAE | The application cannot explicitly close a Connection object while in the middle of a transaction.
adErrFeatureNotAvailable | 3251 0x800A0CB3 | The operation requested by the application is not supported by the provider.
adErrItemNotFound | 3265 0x800A0CC1 | ADO could not find the object in the collection corresponding to the name or ordinal reference requested by the application.
adErrObjectInCollection | 3367 0x800A0D27 | Can't append. The object is already in the collection.
adErrObjectNotSet | 3420 0x800A0D5C | The object referenced by the application no longer points to a valid object.
adErrDataConversion | 3421 0x800A0D5D | The application is using a value of the wrong type for the current operation.
adErrObjectClosed | 3704 0x800A0E78 | The operation requested by the application is not allowed if the object is closed.
adErrObjectOpen | 3705 0x800A0E79 | The operation requested by the application is not allowed if the object is open.
adErrProviderNotFound | 3706 0x800A0E7A | ADO could not find the specified provider.
adErrBoundToCommand | 3707 0x800A0E7B | The application cannot change the ActiveConnection property of a Recordset object with a Command object as its source.
adErrInvalidParamInfo | 3708 0x800A0E7C | The application has improperly defined a Parameter object.
adErrInvalidConnection | 3709 0x800A0E7D | The application requested an operation on an object with a reference to a closed or invalid Connection object.


RDS.DataControl Error Codes

The following table lists the RDS.DataControl object error codes. Both decimal and hexadecimal error code values are shown.

RDS.DataControl error codes | Number | Description
IDS_UpdatesFailed | 4098 0x800A1002 | Unable to update database.
IDS_CantConnect | 4099 0x800A1003 | Unable to connect to server.
IDS_CantCreateObject | 4100 0x800A1004 | Unable to create business object.
IDS_CantInvokeMethod | 4101 0x800A1005 | Unable to invoke method on business object.
IDS_CantFindDataspace | 4102 0x800A1006 | Dataspace property is not valid.
IDS_ObjectNotSafe | 4103 0x800A1007 | Object not safe for scripting and initialization.
IDS_RowsetNotUpdateable | 4104 0x800A1008 | Rowset not updatable.
IDS_BadInlineTablegram | 4105 0x800A1009 | Bad inline tablegram.
IDS_InvalidADCClientVersion | 4106 0x800A1010 | Invalid RDS client version: client is newer than server.
IDS_AsyncPending | 4107 0x800A1011 | Can’t perform operation with an async operation pending.
IDS_ResetInvalidField | 4108 0x800A1012 | The column specified in SortColumn or FilterColumn does not exist.
IDS_RecordsetNotOpen | 4109 0x800A1013 | The recordset is not in an open state.
IDS_InvalidParam | 4110 0x800A1014 | One or more arguments is invalid.
IDS_UnexpectedError | 4351 0x800A10FF | Unexpected error.


Internet Explorer Error Codes

The following table lists Internet Explorer error codes related to Remote Data Service usage. Both decimal and hexadecimal error code values are shown.

Internet Explorer (Wininet) errors | Number | Description
IDS_WinInet_Error | 8193 0x800A2001 | Internet Client Error.
IDS_WinInet_Timeout | 8194 0x800A2002 | Internet Client Error: Request Timeout.
IDS_WinInet_CantConnect | 8195 0x800A2003 | Internet Client Error: Can’t Connect to Server.
IDS_WinInet_SSLPostLimitation | 8196 0x800A2004 | Internet Client Error: SSL Error (possibly 32K data upload limitation).
IDS_WinInet_InvalidServerResponse | 8430 0x800A20EE | Internet Client Error: Invalid Server Response.
IDS_WinInet_ConnectionReset | 12031 0x800A2EFF | Internet Client Error: Connection Reset.


Internet Information Server Error Codes

The following table lists Internet Information Server error codes related to Remote Data Service usage. Both decimal and hexadecimal error code values are shown.

Internet Information Server errors | Number | Description
IDS_IIS_AccessDenied | 8208 0x800A2010 | Internet Server Error: Access Denied.
IDS_IIS_ObjectNotFound | 8209 0x800A2011 | Internet Server Error: Object/Module Not Found.
IDS_IIS_RequestForbidden | 8210 0x800A2012 | Internet Server Error: Request Forbidden.
IDS_IIS_UnexpectedError | 8447 0x800A20FF | Internet Server Error.


Granting Guest Privileges to a Web Server Computer

To grant guest privileges to a Web server computer

  1. On the Windows NT® data source computer, click Start, point to Programs, and click Administrative Tools.

  2. Run User Manager for Domains.

  3. From the User menu, click Select Domain. Enter the current computer name and click OK.

  4. In the lower window, double-click the Guests group and click Add to add the computer name account, which by default would be IUSR_MYWEBSVR (where MYWEBSVR is the name of your Web server).


Required Custom Business Object Registry Entry

To successfully launch a custom business object (.dll or .exe) through the Web server, the business object's ProgID must be entered into the registry as explained in this procedure. This RDS feature protects the security of your Web server by running only sanctioned executables. The default business object, RDSServer.DataFactory, is already fully registered.

To register a custom business object

  1. Point to Start and click Run.

  2. Type RegEdit and click OK.

  3. In the Registry Editor, navigate to the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W3SVC\Parameters\ADCLaunch registry key.

  4. Select the ADCLaunch key, and then from the Edit menu, point to New and click Key.

  5. Type the ProgID of your custom business object and click Enter. Leave the Value entry blank.


Marking Business Objects as Safe for Scripting

To help ensure a secure Internet environment, you need to mark any business objects instantiated with the RDS.DataSpace object's CreateObject method as "safe for scripting." You need to ensure they are marked as such in the License area of the system registry before they can be used in DCOM.

To manually mark your business object as safe for scripting, create a text file with a .reg extension that contains the following text. The following two numbers enable the safe-for-scripting feature:

[HKEY_CLASSES_ROOT\CLSID\<MyActiveXGUID>\Implemented Categories\{7DD95801-9882-11CF-9FA9-00AA006C42C4}]

[HKEY_CLASSES_ROOT\CLSID\<MyActiveXGUID>\Implemented Categories\{7DD95802-9882-11CF-9FA9-00AA006C42C4}]

where <MyActiveXGUID> is the hexadecimal GUID number of your business object. Save it and merge it into your registry by using the Registry Editor or double-clicking directly the .reg file in the Windows Explorer.

Business objects created in Microsoft® Visual Basic® can be automatically marked as "safe for scripting" with the Package and Deployment Wizard. When the wizard asks you to specify safety settings, select Safe for initialization and Safe for scripting.

On the last step, the Application Setup Wizard creates an .htm and a .cab file. You can then copy these two files to the target computer and double-click the .htm file to load the page and correctly register the server.

Because the business object will be installed in the Windows\System32\Occache directory by default, you should move it to the Windows\System32 directory and change HKEY_CLASSES_ROOT\CLSID\<MyActiveXGUID>\InprocServer32 registry key to match the correct path.


Client-side Registry Entries for Business Objects with DCOM

Custom business objects need to ensure that the client side can map their program name (ProgId) to an identifier (CLSID) that can be used over DCOM. For this reason, the ProgID of the DCOM object must be in the client side registry and map to the class ID of the server-side business object. For the other supported protocols (HTTP, HTTPS, and in-process), this isn't necessary.

For example, if you expose a server-side business object called MyBObj with a specific class ID, for instance, "{00112233-4455-6677-8899-00AABBCCDDEE}", you should make sure the following entries are added to the client-side registry:

[HKEY_CLASSES_ROOT]
\MyBObj
   \Clsid
   (Default) "{00112233-4455-6677-8899-00AABBCCDDEE}"

DCOM Stream Marshaling

A client computer using RDS 1.5 or prior components is not compatible with a server using RDS 2.0 components. The newer RDS 2.0 support is more efficient in transporting Recordset objects. If this is the case, you can set your server to work with the previous RDS support (called RDS 1.0) or the newer RDS support (called RDS 2.0). Set either of the following registry entries:

[HKEY_CLASSES_ROOT]
\CLSID
   \[58ECEE30-E715-11CF-B0E3-00AA003F000F}
      \ADTGOptions]"MarshalFormat"="RDS10"

-or-

[HKEY_CLASSES_ROOT]
\CLSID
   \[58ECEE30-E715-11CF-B0E3-00AA003F000F}
      \ADTGOptions]"MarshalFormat"="RDS20"


Enabling a DLL to Run on DCOM

The following steps outline how to enable a business object .dll to use both DCOM and Microsoft® Internet Information Server (HTTP) via Microsoft® Transaction Server.

  1. Create a new empty package in the Transaction Server Explorer.

    You will use the Transaction Server Explorer to create a package and add the DLL into this package. This makes the .dll accessible through DCOM, but it removes the accessibility through IIS. (If you check in the registry for the .dll, the Inproc key is now empty; setting the Activation attribute, explained later in this topic, adds a value in the Inproc key.)

  2. Install a business object into the package.

    -or-

    Import the RDSServer.DataFactory object into the package.

  3. Set the Activation attribute for the component to In the creator's process.

    To make the .dll accessible through DCOM and IIS on the same computer, you must set the component's Activation attribute in the Microsoft Transaction Server Explorer. After you set the attribute to In the creator's process, you will notice that an Inproc server key in the registry has been added that points to a Microsoft Transaction Server surrogate .dll.

See Also For more information about Transaction Server and how to perform these steps, visit the Transaction Server Web site at http://www.microsoft.com/transaction/ or refer to the Microsoft Transaction Server documentation.


Glossary

ActiveX®

business object

business rule

class ID (CLSID)

client tier

Component Object Model (COM)

component

data source

data source tier

data-aware control

DCOM

design time

DLL (dynamic-link library)

marshaling

Microsoft Transaction Server

middle tier

MIME

object variable

ODBC

proxy

recordset

Remote Data Service

rowset

run time

stub

Web server


ADO MD Overview

ADO MD provides easy access to multidimensional data from languages such as Microsoft® Visual Basic®, Microsoft® Visual C++®, and Microsoft® Visual J++™. ADO MD extends Microsoft® ActiveX® Data Objects (ADO) to include objects specific to multidimensional data, such as the CubeDef and Cellset objects. With ADO MD you can browse multidimensional schema, query a cube and retrieve the results.

Like ADO, ADO MD uses an underlying OLE DB provider to gain access to data. To work with ADO MD, the provider must be a multidimensional data provider (MDP) as defined by the OLE DB for OLAP specification. MDPs present data in multidimensional views as opposed to tabular data providers (TDPs) that present data in tabular views. Refer to the documentation for your OLAP OLE DB provider for more detailed information on the specific syntax and behaviors supported by your provider.

This document assumes a working knowledge of the Visual Basic programming language and a general knowledge of databases and OLAP. See Overview of Multidimensional Schemas and Data.


Programming with ADO MD

ADO MD is a dual-interface COM type library. The ADO MD library filename is msadomd.dll, and the program ID (ProgID) is "ADOMD".

To use ADO MD with Microsoft Visual Basic or Microsoft® Office, you should establish a reference to the ADO MD type library. From the Visual Basic IDE:

  1. From the Project menu, click References.

  2. Select the Microsoft ActiveX Data Objects (Multi-Dimensional) check box.

  3. Click OK.

ADO MD objects, methods, and properties will then be accessible through the VBA Object Browser and the IDE Editor.

To use ADO with Microsoft Visual J++, you should create a set of class files using the Java Type Library Wizard. From Microsoft Visual J++:

  1. From the Tools menu, click Java Type Library Wizard.

  2. Select the Microsoft ActiveX Data Objects (Multi-Dimensional) check box.

  3. Click OK.

The wizard will then create the necessary Java class files for ADO MD.


Using ADO with ADO MD

ADO and ADO MD are related but separate object models. ADO provides objects for connecting to data sources, executing commands, retrieving tabular data and schema metadata in a tabular format, and viewing provider error information. ADO MD provides objects for retrieving multidimensional data and viewing multidimensional schema metadata using objects.

When working with an MDP you may choose to use ADO, ADO MD, or both with your application. By referencing both libraries within your project, you will have full access to the functionality provided by your MDP.

It is often useful for consumers to get a flattened, tabular view of a multidimensional dataset. You can do this by using the ADO Recordset object. Specify the source for your Cellset as the Source parameter for the Open method of a Recordset rather than as the source for an ADO MD Cellset.

It may also be useful to view the schema metadata in a tabular view rather than as a hierarchy of objects. The ADO OpenSchema method on the Connection object allows the user to open a Recordset containing schema information. The QueryType parameter of the OpenSchema method has several values that relate specifically to MDPs. These values are:

  • adSchemaCubes

  • adSchemaDimensions

  • adSchemaHierarchies

  • adSchemaLevels

  • adSchemaMeasures

  • adSchemaMembers

For more information about the ADO objects and methods, see the ADO Programmer's Reference.


Overview of Multidimensional Schemas and Data

Understanding Multidimensional Schemas

The central metadata object in ADO MD is the cube, consisting of a structured set of related dimensions, hierarchies, levels, and members. Members can be consolidated or aggregated along one or more hierarchies per dimension, meaning that members can be totaled or "rolled up" in multiple ways.

Dimensions

Consider a Sales Data cube with six dimensions: Salesperson, Geography, Quarters, Years, Measures, and Products. The Geography dimension has the following set of members (only two continents are used for the sake of simplicity):

{All, North America, Europe, Canada, USA, UK, Germany, Canada-West, Canada-East, USA-NW, USA-SW, USA-NE, USA-SE, England, Scotland, Wales, Ireland, Germany-North, Germany-South, Ottawa, Toronto, Vancouver, Calgary, Seattle, Boise, Los Angeles, Houston, Shreveport, Miami, Boston, New York, London, Dover, Glasgow, Edinburgh, Cardiff, Pembroke, Belfast, Londonderry, Berlin, Hamburg, Munich, Stuttgart}

Hierarchies

A natural hierarchy exists in this dimension:

The World
 | Continents
 |  | Countries
 |  |  | Regions
 |  |  |  | Cities

Levels

Each box is a level in the hierarchy. Each level has a set of members, as follows:

  • The World = {All}

  • Continents = {North America, Europe}

  • Countries = {Canada, USA, UK, Germany}

  • Regions = {Canada-East, Canada-West, USA-NE, USA-NW, USA-SE, USA-SW, England, Ireland, Scotland, Wales, Germany-North, Germany-South}

  • Cities = {Ottawa, Toronto, Vancouver, Calgary, Seattle, Boise, Los Angeles, Houston, Shreveport, Miami, Boston, New York, London, Dover, Glasgow, Edinburgh, Cardiff, Pembroke, Belfast, Londonderry, Berlin, Hamburg, Munich, Stuttgart}

Members

Members at the leaf level have no children, and member at the root level have no parents. All other members have at least one parent and at least one child. For example, a partial traversal of the hierarchy tree in the Geography dimension yields the following parent-child relationships:

  • {All} (parent of) {Europe, North America}

  • {North America} (parent of) {Canada, USA}

  • {USA} (parent of) {USA-NE, USA-NW, USA-SE, USA-SW}

  • {USA-NW} (parent of) {Boise, Seattle}

Multiple simultaneous hierarchies (multiple aggregation paths) are often useful. Consider the Time dimension of the Sales Data cube. There are two ways to roll up to the Year level from the Days level:

Year | Year
Quarter | Week
Month | Day of Week
Day of Month |

This example also illustrates another characteristic: Some members of the Week level of the Year-Week hierarchy do not appear in any level of the Year-Quarter hierarchy. Thus, a hierarchy need not include all members of a dimension.


Working with Multidimensional Data

The result of a query on multidimensional data is called a Cellset. A Cellset consists of a collection of axes, usually no more than four axes and typically only two or three. Points along an axis are called positions. For an axis consisting of a single dimension, these positions are a subset of the dimension members. If an axis consists of more than one dimension, then each position is a compound entity, which has n parts where n is the number of dimensions oriented along that axis. Each part of the position is a member from one constituent dimension.

For example, if the Geography and Product dimensions from the Sales Data cube are oriented along the x-axis of a Cellset, a position along this axis may contain the members "USA" and "Computers." In this example, determining a position along the x-axis requires that members from each dimension are oriented along the axis.

The objects positioned at the intersection of axis coordinates are called cells. Each cell has multiple pieces of information associated with it, including the data itself, a formatted string (the displayable form of cell data), and the cell ordinal value. (Each cell is a unique ordinal value in the Cellset. The ordinal value of the first cell in the Cellset is zero, while the leftmost cell in the second row of a Cellset with eight columns would be eight.)

For example, consider a Sales Data cube that has the following six dimensions:

  • Salesperson

  • Geography (natural hierarchy)—Continents, Countries, States, and so on

  • Quarters—Quarters, Months, Days

  • Years

  • Measures—Sales, PercentChange, BudgetedSales

  • Products

Consider the following Cellset:

Sales for 1991, All Products

 |  | Venkatrao |  |  |  | Netz
 |  | USA |  |  | Japan | USA |  |  | Japan
 |  | USA_ North |  | USA_ South |  | USA_ North |  | USA_ South |
 |  | Seattle | Boston |  |  | Seattle | Boston |  |
 | Jan | 00 | 10 | 20 | 30 | 40 | 50 | 60 | 70
Qtr1 | Feb | 01 | 11 | 21 | 31 | 41 | 51 | 61 | 71
 | Mar | 02 | 12 | 22 | 32 | 42 | 52 | 62 | 72
Qtr2 |  | 03 | 13 | 23 | 33 | 43 | 53 | 63 | 73
Qtr3 |  | 04 | 14 | 24 | 34 | 44 | 54 | 64 | 74
 | Oct | 05 | 15 | 25 | 35 | 45 | 55 | 65 | 75
Qtr4 | Nov | 06 | 16 | 26 | 36 | 46 | 56 | 66 | 76
 | Dec | 07 | 17 | 27 | 37 | 47 | 57 | 67 | 77

Note The cell values in the example can be viewed as ordered pairs of axis position ordinals where the first digit represents the x-axis position and the second digit the y-axis position.

The characteristics of this Cellset are as follows:

  • Axis dimensions: Quarters, Salesperson, Geography

  • Filter dimensions: Measures, Years, Products

  • Two axes: COLUMN (x, or Axis 0) and ROW (y, or Axis 1)

  • x-axis: two nested dimensions, Salesperson and Geography

  • y-axis: Quarters dimension

The x-axis has two nested dimensions: Salesperson and Geography. From Geography, four members are selected: Seattle, Boston, USA_South, and Japan. Two members are selected from Salesperson: Venkatrao and Netz. This yields a total of eight positions on this axis (8 = 4*2).

Each coordinate is represented as a position with two members—one from the Salesperson dimension and another from the Geography dimension:

(Venkatrao, Seattle), (Venkatrao, Boston), (Venkatrao, USA_North), (Venkatrao, Japan), (Netz, Seattle), (Netz, Boston), (Netz, USA_North), (Netz, Japan)

The y-axis has only one dimension. It contains the following eight positions:

Jan, Feb, Mar, Qtr2, Qtr3, Oct, Nov, Dec


ADO MD Object Model

The following diagram shows how these objects are represented and related in ADO MD.

Each of the Axis and Cell objects also has a Positions collection.


Axis Object (ADO MD)

An Axis object contains selected members of one or more dimensions. The Member objects are contained in a Positions collection.

Remarks

An Axis object can be contained by an Axes collection, or returned by the FilterAxis property of a Cellset.

With the collections and properties of an Axis object, you can do the following:

  • Iterate through each position along an Axis using the Positions collection.

  • Obtain the number of dimensions on the Axis with the DimensionCount property.


Catalog Object (ADO MD)

A Catalog object contains the CubeDefs collection that makes up a multidimensional schema.

Remarks

With the collections and properties of a Catalog object, you can do the following:

  • Open the catalog by setting the ActiveConnection property to an ADO Connection object or a valid connection string.

  • Iterate through the cubes in a catalog using the CubeDefs collection.


Cell Object (ADO MD)

A Cell object represents the data at the intersection of axis coordinates.

Remarks

A Cell object is returned by the Item method of a Cellset object.

With the collections and properties of a Cell object, you can do the following:

  • Return the data in the Cell with the Value property.

  • Return the string representing the formatted display of the Value property with the FormattedValue property.

  • Return the ordinal value of the Cell within the Cellset with the Ordinal property.

  • Determine the position of the Cell within the CubeDef with the Positions collection.

  • Retrieve other information about the Cell with the Properties collection.

The Properties collection contains provider-supplied properties. The following table lists properties that may be available. The actual property list may differ depending upon the implementation of the provider. See the documentation for your provider for a more complete list of available properties.

Name | Description
BackColor | Background color to use when displaying the cell.
ForeColor | Foreground color to use when displaying the cell.
FormatString | Value in a formatted string.
FontName | Font used to display the cell value.
FontSize | Font size used to display the cell value.
FontFlags | Bitmask detailing effects on the font.


Cellset Object (ADO MD)

A Cellset represents the results of a multidimensional query.

Remarks

Data within a Cellset is retrieved using direct, array-like access. There is no notion of currency within a Cellset. The Item method retrieves a Cell object corresponding to the Axis position specified.

With the collections, methods, and properties of a Cellset object, you can do the following:

  • Return or specify the query used to define the Cellset with the Source property.

  • Execute and retrieve the results of a multidimensional query with the Open method.

  • Retrieve a Cell from the Cellset with the Item method.

  • Return the Axis objects that define the Cellset with the Axes collection.

  • Retrieve information on the dimensions used to filter the data in the Cellset with the FilterAxis property.

  • Associate an open connection with a Cellset object by setting its ActiveConnection property.

  • Close an open Cellset with the Close method.

  • Return the current state of the Cellset (Open, Closed, Executing, or Connecting) with the State property.


CubeDef Object (ADO MD)

A CubeDef object represents a cube containing a set of related Dimensions.

Remarks

With the collections and properties of a CubeDef object, you can do the following:

  • Identify a CubeDef with the Name property.

  • Return a string that describes the cube with the Description property.

  • Return the dimensions that make up the cube with the Dimensions collection.

  • Use the Properties collection to obtain additional information about the CubeDef.

The Properties collection contains provider-supplied properties. The following properties should be available, but the actual property list may differ depending upon the implementation of the provider. See the documentation for your provider for a more complete list of available properties.

Name | Description
CatalogName | The name of the catalog to which this cube belongs.
SchemaName | The name of the schema to which this cube belongs.
CubeName | The name of the cube.
CubeType | The type of the cube.
CubeGUID | Cube GUID.
CreatedOn | Date and time of cube creation.
LastSchemaUpdate | Date and time of last schema update.
SchemaUpdatedBy | User ID of the person doing the last schema update.
DataUpdatedBy | User ID of the person doing the last data update.
Description | A meaningful description of the cube.


Dimension Object (ADO MD)

A Dimension object represents a dimension of a cube, and contains one or more Hierarchies of Members.

Remarks

A Dimension object can be contained by a Dimensions collection.

With the collections and properties of a Dimension object, you can do the following:

  • Identify the Dimension with the Name and UniqueName properties.

  • Return a meaningful string that describes the Dimension with the Description property.

  • Return the Hierarchies that make up the Dimension with the Hierarchies collection.

  • Use the Properties collection to obtain additional information about the Dimension object.

The Properties collection contains provider-supplied properties. The following properties should be available, but the actual property list may differ depending upon the implementation of the provider. See the documentation for your provider for a more complete list of available properties.

Name | Description
CatalogName | The name of the catalog to which this cube belongs.
SchemaName | The name of the schema to which this cube belongs.
CubeName | The name of the cube.
DimensionName | The name of the dimension.
DimensionUniqueName | The unique name of the dimension.
DimensionGUID | The GUID of the dimension.
DimensionCaption | A label or caption associated with the dimension.
DimensionOrdinal | The ordinal number of the dimension among the group of dimensions that form the cube.
DimensionType | The dimension type.
DimensionCardinality | The number of members in the dimension.
DefaultHierarchy | The unique name of the default hierarchy.
Description | A meaningful description of the cube.


Hierarchy Object (ADO MD)

A Hierarchy object represents the ways in which the Members of a Dimension can be aggregated or "rolled up." A Dimension can be aggregated along one or more Hierarchy.

Remarks

A Hierarchy object can be contained by a Hierarchies collection.

With the collections and properties of a Hierarchy object, you can do the following:

  • Identify the Hierarchy with the Name and UniqueName properties.

  • Return a meaningful string that describes the Hierarchy with the Description property.

  • Return the Levels that make up the Hierarchy with the Levels collection.

  • Use the Properties collection to obtain additional information about the Hierarchy object.

The Properties collection contains provider-supplied properties. The following properties should be available, but the actual property list may differ depending upon the implementation of the provider. See the documentation for your provider for a more complete list of available properties.

Name | Description
CatalogName | The name of the catalog to which this cube belongs.
SchemaName | The name of the schema to which this cube belongs.
CubeName | The name of the cube.
DimensionUniqueName | The unique name of the dimension.
HierarchyName | The name of the hierarchy.
HierarchyUniqueName | The unique name of the hierarchy.
HierarchyGUID | The GUID of the hierarchy.
HierarchyCaption | A label or caption associated with the hierarchy.
DimensionType | The type of dimension to which this hierarchy belongs.
HierarchyCardinality. | The number of members in the hierarchy.
DefaultMember | The unique name of the default member for this hierarchy.
AllMember | The member at the highest level of rollup in the hierarchy.
Description | A meaningful description of the hierarchy.


Level Object (ADO MD)

A Level object contains a set of Members, each of which has the same rank within a Hierarchy.

Remarks

A Level object can be contained by a Levels collection.

With the collections and properties of a Level object, you can do the following:

  • Identify the Level with the Name and UniqueName properties.

  • Return a meaningful string that describes the Level with the Description property.

  • Return a string to use when displaying the Level with the Caption property.

  • Return the number of levels from the root of the Level with the Depth property.

  • Return the Members that make up the Level with the Members collection.

  • Use the Properties collection to obtain additional information about the Level object.

The Properties collection contains provider-supplied properties. The following properties should be available, but the actual property list may differ depending upon the implementation of the provider. See the documentation for your provider for a more complete list of available properties.

Name | Description
CatalogName | The name of the catalog to which this cube belongs.
SchemaName | The name of the schema to which this cube belongs.
CubeName | The name of the cube.
DimensionUniqueName | The unique name of the dimension.
HierarchyUniqueName | The unique name of the hierarchy.
LevelName | Name of the level.
LevelUniqueName | The unique name of the level.
LevelGUID | The GUID of the level.
LevelCaption | A label or caption associated with the level.
LevelNumber | The distance of the level from the root of the hierarchy.
LevelCardinality | The number of members in a level.
LevelType | The type of level.
Description | A meaningful description of the level.


Member Object (ADO MD)

A Member object can represent either a Member of a Level in a CubeDef or a Member of a Position along an Axis in a Cellset. The properties of a Member are slightly different depending on the context in which it is used.

A Member of a CubeDef has a Children collection that contains child members of the current member on the next lower level in the hierarchy. For a Member of a Cellset, the Children collection is always empty.

A Member of a Cellset has two properties, DrilledDown and ParentSameAsPrev, which are useful when displaying the Cellset. An error will occur if these properties are accessed on a member of a CubeDef.

Remarks

With the collections and properties of a Member object in a CubeDef, you can do the following:

  • Identify the Member with the Name and UniqueName properties.

  • Return a meaningful string that describes a measure or formula Member with the Description property.

  • Return a string to use when displaying the Member with the Caption property.

  • Obtain related Members in a Hierarchy with the Parent and Children properties.

  • Determine the nature of the Member with the Type property.

  • Obtain information about the Level of the Member with the LevelDepth and LevelName properties.

  • Use the Properties collection to obtain additional information about the Level object.

With the collections and properties of a Member of a Position along an Axis, you can do the following:

  • Identify the Member with the Name and UniqueName properties.

  • Return a meaningful string that describes a measure or formula Member with the Description property.

  • Return a string to use when displaying the Member with the Caption property.

  • Determine the nature of the Member with the Type property.

  • Obtain information about the Level of the Member with the LevelDepth and LevelName properties.

  • Use the Properties collection to obtain additional information about the Level object.

The Properties collection contains provider-supplied properties. The following properties should be available, but the actual property list may differ depending upon the implementation of the provider. See the documentation for your provider for a more complete list of available properties.

Name | Description
CatalogName | The name of the catalog to which this cube belongs.
SchemaName | The name of the schema to which this cube belongs.
CubeName | The name of the cube.
DimensionUniqueName | The unique name of the dimension.
HierarchyUniqueName | The unique name of the hierarchy.
LevelUniqueName | The unique name of the level.
LevelNumber | The distance of the level from the root of the hierarchy.
MemberOrdinal | The ordinal number of the member.
MemberName | The name of the member.
MemberUniqueName | The unique name of the member.
MemberType | The type of the member.
MemberGUID | The GUID of the member.
MemberCaption | A label or caption associated with the member.
ChildrenCardinality | The number of children that the member has.
ParentLevel | The level number of the member's parent.
ParentUniqueName | The unique name of the member's parent.
ParentCount | The count of the number of parents that this member has.
Description | A meaningful description of the member.


Position Object (ADO MD)

A Position object is a set of one or more Members of different dimensions that defines a point along an Axis.

Remarks

A Position object is contained by the Positions collection.

Use the Ordinal property to return the ordinal position of the Position along the Axis.

See the Members collection topic for a more detailed explanation of how to use Members.


Axes Collection (ADO MD)

An Axes collection contains the Axis objects that define a Cellset object.

Remarks

A Cellset object contains an Axes collection. Once the Cellset is opened this collection will contain at least one Axis. See the Axis object topic for a more detailed explanation of how to use Axis objects.

Note The filter axis of a Cellset is not contained in the Axes collection. See the FilterAxis property topic for more information.


CubeDefs Collection (ADO MD)

A CubeDefs collection contains the CubeDef objects that represent a multidimensional catalog or schema.

Remarks

Use the Refresh method to update the CubeDef objects in the collection to represent the current catalog’s schema.

See the CubeDef object topic for a more detailed explanation of how to use CubeDef objects.


Dimensions Collection (ADO MD)

A Dimensions collection contains the Dimension objects that make up a CubeDef object.

Remarks

A CubeDef object contains a Dimensions collection.

Use the Refresh method to update the Dimension objects in the collection to represent the current catalog’s schema.

See the Dimension object topic for a more detailed explanation of how to use Dimension objects.


Hierarchies Collection (ADO MD)

A Hierarchies collection contains the set Hierarchy objects of a Dimension.

Remarks

A Dimension object can contain a Hierarchies collection.

Use the Refresh method to update the Hierarchy objects in the collection to represent the current catalog’s schema.

See the Hierarchy object topic for a more detailed explanation of how to use Hierarchy objects.


Levels Collection (ADO MD)

A Levels collection contains the Level objects that make up a Hierarchy.

Remarks

A Hierarchy object can contain a Levels collection.

Use the Refresh method to update the Level objects in the collection to represent the current catalog’s schema.

See the Level object topic for a more detailed explanation of how to use Level objects.


Members Collection (ADO MD)

A Members collection contains one or more related Member objects.

Remarks

A Level or Position object can contain a Members collection, or the Children property of a Member object can return a Members collection.

Use the Refresh method to update the Member objects in the collection to represent the current catalog’s schema.

See the Member object topic for a more detailed explanation of how to use Member objects.


Positions Collection (ADO MD)

A Positions collection contains the Position objects that make up an Axis.

Remarks

An Axis or Cell object can contain a Positions collection.

See the Position object topic for a more detailed explanation of how to use Position objects.


Close Method (ADO MD)

The Close method closes an open Cellset object.

Syntax

Cellset.Close

Remarks

Using the Close method to close a Cellset object releases the associated data, including data in any related Cell, Axis, Position, or Member objects. Closing a Cellset does not remove it from memory; you can change its property settings and open it again later. To completely eliminate an object from memory, set the object variable to Nothing.

You can later call the Open method to reopen the Cellset using the same or another Source string. While the Cellset object is closed, retrieving any properties or calling any methods that reference the underlying data or metadata generates an error.


Item Method (ADO MD Cellset)

The Item method retrieves a Cell from a Cellset using its coordinates.

Syntax

Set Cell = Cellset.Item ( Positions )

Parameters

Positions Variant Array of values that uniquely specify a Cell. Positions can be one of the following:

  • An array of position numbers

  • An array of member names

  • The ordinal position

Remarks

Use the Item method to return a Cell within the Cellset. If the Item method cannot find the cell corresponding to the Positions argument, an error occurs.

The Item method is the default method for the Cellset object. The following syntax forms are interchangeable:

Cellset.Item ( Positions )

Cellset ( Positions )

The Positions argument is used to specify which cell to return. You can specify the cell by ordinal position or by the position along each axis. When specifying the cell by position along each axis, you can specify the numeric value of the position or the names of the members for each position.

The ordinal position is a number that uniquely identifies one cell within the Cellset. Conceptually, cells are numbered in a Cellset as if the Cellset were a p-dimensional array, where p is the number of axes. Cells are addressed in row-major order. Below is the formula for calculating the ordinal number of a cell:

If member names are passed as strings to Item, the members must be listed in increasing order of the numeric axis identifiers. Within an axis, the members must be listed in increasing order of dimension nesting—that is, the outermost dimension’s member comes first, followed by members of inner dimensions. Each dimension should be represented by a separate string, and the list of member strings should be separated by commas.


Item Method (ADO MD Collection)

The Item method retrieves an item from a collection by name or ordinal number.

Syntax

Set Object = Collection.Item ( Index )

Parameters

Index Variant that evaluates to either the string containing the name or the ordinal number of an object in the collection.

Remarks

Use the Item method to return a specific object in a collection. If the method cannot find an object in the collection corresponding to the Index argument, an error occurs. Also, some collections do not support named objects; for these collections, you must use ordinal number references.

The Item method is the default method for all collections. The following syntax forms are interchangeable:

Collection.Item ( Index )

Collection ( Index )


Open Method (ADO MD)

The Open method retrieves the results of a multidimensional query.

Syntax

Cellset.Open Source, ActiveConnection

Parameters

Source Optional. A Variant that evaluates to a valid multidimensional query, such as an MDX query. The Source argument corresponds to the Source property. For more information about MDX, see the OLE DB for OLAP specification.

ActiveConnection Optional. A Variant that evaluates to a string specifying either a valid ADO Connection object variable name or a definition for a connection. The ActiveConnection argument specifies the connection in which to open the Cellset object. If you pass a connection definition for this argument, ADO opens a new connection using the specified parameters. The ActiveConnection argument corresponds to the ActiveConnection property.

Remarks

The Open method generates an error if either of its parameters is omitted and its corresponding property value has not been set prior to attempting to open the Cellset.


Refresh Method (ADO MD)

The Refresh method updates the objects in the collection to reflect the current catalog’s schema.

Syntax

Collection.Refresh


ActiveConnection Property (ADO MD)

The ActiveConnection property indicates to which Connection object the current Cellset or Catalog currently belongs.

Settings and Return Values

ActiveConnection sets or returns a Variant that contains a String defining a connection or Connection object. Default is empty. ActiveConnection is read/write.

Remarks

You can set this property to a valid ADO Connection object or to a valid connection string. When this property is set to a connection string, the provider creates a new Connection object using this definition and opens the connection.

If you use the ActiveConnection argument of the Open method to open a Cellset object, the ActiveConnection property will inherit the value of the argument.

Setting the ActiveConnection property of a Catalog object to Nothing releases the associated data, including data in the CubeDefs collection and any related Dimension, Hierarchy, Level, and Member objects. Closing a Connection object that was used to open a Catalog has the same effect as setting the ActiveConnection property to Nothing.

An error will occur if you attempt to change the ActiveConnection property for an open Cellset object.

Note Remember to use the Set keyword when setting the ActiveConnection property to a Connection object. If you omit the Set keyword you will actually be setting the ActiveConnection property equal to the Connection object's default property: ConnectionString. The code will work; however, you will create an additional connection to the data source, which may have negative performance implications.

To specify a connection string to an OLAP server, the Data Source property should be set to a Data Source name supported by the server. To connect to a cube file that is disconnected from a server, set the Location property to the full path to the .CUB file. In either case, the Provider property should be set to a provider name. For example, the following string connects to a Data Source named Bobs Video Store with a Provider named msolap:

"Data Source=Bobs Video Store;Provider=msolap"

The following string connects to a local cube file at the location C:\MSDASDK\samples\oledb\olap\data\bobsvid.cub:

"Location=C:\MSDASDK\samples\oledb\olap\data\bobsvid.cub;Provider=msolap"


Caption Property (ADO MD)

Text caption to use when displaying a Level or Member.

Return Values

Caption returns a string and is read-only.


ChildCount Property (ADO MD)

The ChildCount property specifies the number of Members for which the current Member is the parent.

Return Values

ChildCount returns a Long integer, and is read-only.

Remarks

Use the ChildCount property to find out how many children a Member has. This may be an estimate of the number of children, and not exact.

For Member objects in a Cellset the maximum number returned is 65536. If the actual number of children exceeds 65536, the value returned will still be 65536. Therefore, the application should interpret a ChildCount of 65536 as greater than or equal to 65536 children.

For Member objects in a CubeDef you can determine the exact number of children by using the Count property on the Children collection. Determining the exact number of children may be slow if the number of children in the collection is large.


Children Property (ADO MD)

The Children property returns a collection of Members for which the current Member is the parent in the hierarchy.

Return Values

Children returns a Members collection, and is read-only.

Remarks

The Children collection contains Members for which this Member is the hierarchical parent. Leaf level Members will have zero (0) Members in this collection. This property is only supported on Member objects belonging to a Level object. An error occurs when this property is referenced from Member objects belonging to a Position object.


Count Property (ADO MD)

The Count property returns the number of objects in the current collection.

Return Values

Count returns a Long integer, and is read-only.

Remarks

Use the Count property to determine how many objects are in a given collection.

Because numbering for members of a collection begins with zero, you should always code loops starting with the zero member and ending with the value of the Count property minus one. If you are using Microsoft Visual Basic and want to loop through the members of a collection without checking the Count property, use the For Each...Next command.

If the Count property is zero, there are no objects in the collection.


Depth Property (ADO MD)

The Depth property specifies the number of levels the Level is from the root of the hierarchy Level.

Return Values

Depth returns an Integer, and is read-only.


Description Property (ADO MD)

The Description property provides meaningful text that explains the current object.

Return Values

Description is a string and is read-only.

Remarks

For Member objects, Description applies only to measure and formula members. Description returns an empty string ("") for all other types of members. For more information about the various types of members, see the Type property.

This property is only supported on Member objects belonging to a Level object. An error occurs when this property is referenced from Member objects belonging to a Position object.


DimensionCount Property (ADO MD)

The DimensionCount property returns the number of dimensions on an axis.

Return Values

DimensionCount returns a Long integer, and is read-only.


DrilledDown Property (ADO MD)

The DrilledDown property indicates whether the member is drilled down.

Return Values

DrilledDown returns a Boolean value and is read-only.

Remarks

Use the DrilledDown property to determine whether there is at least one child of this member on the axis immediately following this member. This information is often useful when displaying the member.

This property is only supported on Member objects belonging to a Position object. An error occurs when this property is referenced from Member objects belonging to a Level object.


FilterAxis Property (ADO MD)

The FilterAxis property returns an Axis object containing filter information for the current Cellset.

Return Values

FilterAxis returns an Axis, and is read-only.

Remarks

Use the FilterAxis property to return information on the dimensions that were used to slice the data. The DimensionCount property of the Axis returns the number of slicer dimensions. This axis usually has just one row.

The Axis returned by FilterAxis is not contained in the Axes collection for a Cellset.


FormattedValue Property (ADO MD)

The FormattedValue property returns a text string representing the formatted display of a Cell value.

Return Values

FormattedValue returns a string and is read-only.

Remarks

Use the FormattedValue property to obtain the value of the Value property, formatted for display. For example, if the value of a Cell was 1056.87, and this value represented a dollar amount, FormattedValue would be $1,056.87.


LevelDepth Property (ADO MD)

The LevelDepth property returns the number of levels from the root of the hierarchy to a member.

Return Values

LevelDepth returns a Long integer, and is read-only.

Remarks

Use the LevelDepth property to determine the distance of the Member object from the root level of the hierarchy. The LevelDepth of a member at the root level is 0.


LevelName Property (ADO MD)

The LevelName property returns the name of the level of a member.

Return Values

LevelName returns a string and is read-only.

Remarks

Use the LevelName property to retrieve the name of the level to which a member belongs.


Name Property (ADO MD)

The Name property indicates the name of an object.

Return Values

Name returns a string and is read-only.

Remarks

You can retrieve the Name property of an object by an ordinal reference, after which you can refer to the object directly by name. For example, if cdf.CubeDefs(0).Name yields "Bobs Video Store," you can refer to this CubeDef as cdf.CubeDefs("Bobs Video Store").


Ordinal Property (ADO MD Cell)

Return Values

Ordinal returns a Long integer and is read-only.

Remarks

The cell's ordinal value uniquely identifies the Cell within the Cellset. Conceptually, cells are numbered in a Cellset as if the Cellset were a p-dimensional array, where p is the number of axes. Cells are numbered starting from zero in row-major order. Here is the formula for calculating the ordinal number of a cell:

The cell's ordinal value can be used with the Item method of the Cellset object to quickly retrieve the cell.


Ordinal Property (ADO MD Position)

Return Values

Ordinal returns a Long integer and is read-only.

Remarks

The Ordinal of a Position object corresponds to the index of the Position within the Positions collection.

A cell can quickly be retrieved using the Ordinal of the Position along each axis with the Item method of the Cellset object.


Parent Property (ADO MD)

The Parent property returns the Member object that is the parent of the current member in the hierarchy.

Return Values

Parent returns a Member object and is read-only.

Remarks

A member that is at the top level of a hierarchy (the root) has no parent. This property is supported only on Member objects belonging to a Level object. An error occurs when this property is referenced from Member objects belonging to a Position object.


ParentSameAsPrev Property (ADO MD)

The ParentSameAsPrev property indicates whether the parent of this member is the same as the parent of the immediately preceding member.

Return Values

ParentSameAsPrev returns a Boolean value and is read-only.

Remarks

This property is supported only on Member objects belonging to a Position object. An error occurs when this property is referenced from Member objects belonging to a Level object.


Source Property (ADO MD)

The Source property indicates the source for the data in the Cellset.

Settings and Return Values

Source sets and returns a Variant, and is read/write for closed Cellsets and read-only for open Cellsets. The Variant should contain a valid MDX query string.


State Property (ADO MD)

The State property indicates the current state of the Cellset.

Return Values

State returns a Long integer indicating the current condition of the Cellset. The following values are valid:

Value | Description | Name
0 | The Cellset is closed. | adStateClosed
1 | The Cellset is open. | adStateOpen

State is read-only.

Remarks

To use the constant names, you must have the ADO type library referenced in your project. See the section Using ADO with ADO MD for more information.


Type Property (ADO MD)

The Type property indicates the type of the current Member.

Return Values

Type returns an Enumeration and is read-only.

The Type property can be one of the following values:

Name | Value | Description
adMemberlRegular | 1 | Default. Member represents an instance of a business entity.
adMemberAll | 8 | Member represents all members of the level.
adMemberMeasure | 2 | Member belongs to the Measures dimension. It represents a quantitative attribute.
adMemberFormula | 4 | Member is calculated using a formula expression.
adMemberUnknown | 16 | The type cannot be determined.

Remarks

This property is supported only on Member objects belonging to a Level object. An error occurs when this property is referenced from Member objects belonging to a Position object.


UniqueName Property (ADO MD)

The UniqueName property specifies an unambiguous name for the current object.

Return Values

UniqueName returns a string and is read-only.


Value Property (ADO MD)

The Value property specifies the value of the current Cell.

Return Values

Value returns a Variant and is read-only.


Cellset Example (ADO MD)

Cellset Example

The following code demonstrates how to open a Cellset, print captions of the Members for each position and print the formatted value of the Cell. This code assumes there is a Data Source named Bobs Video Store on the OLAP server.

Dim cat     As New ADOMD.Catalog
Dim cst     As New ADOMD.Cellset
Dim axs     As ADOMD.Axis
Dim i       As Integer
Dim j       As Integer
cat.ActiveConnection = "Data Source=Bobs Video Store;Provider=msolap;"
cst.Source = "SELECT [Product Category].MEMBERS ON ROWS, _
                     [Store State].MEMBERS ON COLUMNS _
              FROM   [Bobs Video Store] _
              WHERE  ([Quantity])"
Set cst.ActiveConnection = cat.ActiveConnection
cst.Open
For i = 0 To cst.Axes(0).Positions.Count - 1
    Debug.Print cst.Axes(0).Positions(i).Members(0).Caption & " ";
    Set axs = cst.Axes(1)
    For j = 0 To axs.Positions.Count - 1
        Debug.Print "     " & axs.Positions(j).Members(0).Caption & _
          " " & cst(i, j).FormattedValue
    Next
Next


CubeDef Example (ADO MD)

CubeDef Example

This code example demonstrates how to access the CubeDefs and Dimensions collections. It prints the name of each dimension in a cube. This code assumes there is a Data Source named Bobs Video Store on the OLAP server.

Dim cat     As New ADOMD.Catalog
Dim cdf     As ADOMD.CubeDef
Dim i       As Integer
cat.ActiveConnection = "Data Source=Bobs Video Store;Provider=msolap;"
Set cdf = cat.CubeDefs("Bobs Video Store")
For i = 0 To cdf.Dimensions.Count - 1
    Debug.Print cdf.Dimensions(i).Name
Next


Cell Example (ADO MD)

Cell Example

The following code demonstrates the three methods of accessing a given cell. This code assumes there is a Data Source named Bobs Video Store on the OLAP server:

Dim cat     As New ADOMD.Catalog
Dim cst     As New ADOMD.Cellset
Dim cll     As ADOMD.Cell
cat.ActiveConnection = "Data Source=Bobs Video Store;Provider=msolap;"
cst.Source = "SELECT [Product Category].MEMBERS ON ROWS, _
                     [Store State].MEMBERS ON COLUMNS _
              FROM   [Bobs Video Store] _
              WHERE  ([Quantity])"
Set cst.ActiveConnection = cat.ActiveConnection
cst.Open
'Retrieve cell using ordinal position
Set cll = cst(10)
'Retrieve cell using axis numerical position
Set cll = cst(2,2)
'Retrieve cell using member names
Set cll = cst("Childrens", "New York State")


Connection Example (ADO MD)

Connection Example

The following code demonstrates how to set the ActiveConnection property using a connection string. This code assumes there is a Data Source named Bobs Video Store on the OLAP server:

Dim cat As New ADOMD.Catalog
cat.ActiveConnection = "Data Source=Bobs Video Store;Provider=msolap;"

The following code also demonstrates how to set the ActiveConnection property using a connection string. However, this code connects to a local cube file with no connection to an OLAP server:

Dim cat As New ADOMD.Catalog
cat.ActiveConnection = _
"Location=C:\MSDASDK\samples\oledb\olap\data\BobsVid.cub;" + _
"Provider=msolap;"

The following code demonstrates how to set the ActiveConnection property to an ADO Connection object. You must have a reference to the ADO type library in your project in order to use the ADO Connection object.

Dim dnn  As New ADODB.Connection
Dim cat  As New ADOMD.Catalog
Cnn.Open "Data Source=Bobs Video Store;Provider=msolap;"
Set cat.ActiveConnection = cnn

Note Remember to use the Set keyword when setting the ActiveConnection property to a Connection object. If you omit the Set keyword you will actually be setting the ActiveConnection property equal to the Connection object's default property: ConnectionString. The code will work; however, you will create an additional connection to the data source, which may have negative performance implications.


rowset <definition>

rowset

The set of rows returned in a single fetch by a block cursor.


component <definition>

component

A discrete unit of code built on ActiveX® technologies that delivers a well-specified set of services through well-specified interfaces. Components provide the objects that clients request at run time. In Remote Data Service, components are also referred to as business objects when they include key logic for supporting business processes.


Component Object Model (COM) <definition>

Component Object Model (COM)

An open architecture for cross-platform development of client/server applications based on object-oriented technology. Clients have access to an object through interfaces implemented on the object. COM is language neutral, so any language that produces ActiveX® components can also produce COM applications.


DLL (dynamic-link library) <definition>

DLL (dynamic-link library)

A file that contains one or more functions that are compiled, linked, and stored separately from the processes that use them. The operating system maps the DLLs into the address space of the calling process when the process is starting or while it is running.


data-aware control <definition>

data-aware control

A control that is able to use data from a database. Once you bind the control to a database via the RDS.DataControl object, the control is referred to as a bound control.


Web server <definition>

Web server

A computer that provides Web services and pages to intranet and Internet users. Internet Information Server is installed on your Web server, and server-side business objects are typically instantiated here.


object variable <definition>

object variable

A variable that contains a reference to an object. For example, objCustomObject is a variable that points to an object of type CustomObject:

Set objCustomObject = ADS1.CreateObject("CustomObject", _
   "http://SalesWeb")


DCOM <definition>

DCOM (Distributed Component Object Model)

An object protocol that enables ActiveX® components to communicate directly with each other across a network. DCOM is language neutral, so any language that produces ActiveX components can also produce DCOM applications.


proxy <definition>

proxy

An interface-specific object that provides the parameter marshaling and communication required for a client to call an application object that is running in a different execution environment, such as on a different thread or in another process. The proxy is located with the client and communicates with a corresponding stub that is located with the application object that is being called.


MIME <definition>

MIME

A standard that allows binary data to be published and read on the Internet. The header of a file with binary data contains the MIME type of the data; this informs client programs (Web browsers and mail packages, for instance) that they will need to handle the data in a different way than they handle straight text. For example, the header of a Web document containing a JPEG graphic contains the MIME type specific to the JPEG file format. This allows a browser to display the file with its JPEG viewer, if one is present.


ActiveX <definition>

ActiveX®

A set of technologies that enables software components to interact with one another in a networked environment, regardless of the language in which they were created. ActiveX® is built on the Component Object Model (COM).


ODBC <definition>

ODBC (Open Database Connectivity)

A standard programming language interface used to connect to a variety of data sources. This is usually accessed through Control Panel, where data source names (DSNs) can be assigned to use specific ODBC drivers.


middle tier <definition>

middle tier

Also known as application server tier. The logical layer between a user interface or Web client and the database. This is typically where the Web server resides, and where business objects are instantiated. The middle tier is a collection of business rules and functions that generate and operate upon receiving information. They accomplish this through business rules, which can change frequently, and are thus encapsulated into components that are physically separate from the application logic itself. See also client tier, data source tier.


data source <definition>

data source

The name that applications use to request a connection to a system ODBC data source. It specifies the computer name and (optionally) database that the data source name (DSN) maps to.

A System data source is a data source that is available to anyone using the computer. Data sources that will be used with a Web server need to be System data sources.


data source tier <definition>

data source tier

A logical layer that represents a computer running a DBMS, such as an SQL Server database. See also client tier, middle tier.


Remote Data Service <definition>

Remote Data Service

A high-performance Web-based technology that brings database connectivity and corporate data publishing capabilities to Internet and intranet applications.


Microsoft Transaction Server <definition>

Microsoft Transaction Server

A component-based transaction processing system for developing, deploying, and managing high-performance, scalable, and robust enterprise, Internet, and intranet server applications. Microsoft ® Transaction Server defines an application programming model for developing distributed, component-based applications. It also provides a run-time infrastructure for deploying and managing these applications.


class ID (CLSID) <definition>

class ID (CLSID)

A universally unique identifier (UUID) that identifies a COM component. Each COM component has its CLSID in the Windows Registry so that it can be loaded by other applications.


business object <definition>

business object

An ActiveX® component that retrieves and processes the data. Business objects are usually on the middle tier.

Remote Data Service provides a default middle-tier business object, RDSServer.DataFactory, that receives client requests and provides read and write access to specified data sources, but that does not contain any validation or business rules logic.

You can create custom business objects that can provide the same functionality as RDSServer.DataFactory, as well as encapsulate your application's business rules.


stub <definition>

stub

An interface-specific object that provides the parameter marshaling and communication required for an application object to receive calls from a client that is running in a different execution environment, such as on a different thread or in another process. The stub is located with the application object and communicates with a corresponding proxy that is located with the client that calls it.


recordset <definition>

recordset

A rowset provided through ActiveX® Data Objects (ADO).


client tier <definition>

client tier

A logical layer that represents a local computer where browser software displays a Web page. See also middle tier, data source tier.


design time <definition>

design time

The time during which you build an application in the development environment by adding controls, setting control or form properties, and so on. In contrast, during run time, you interact with the application as a user would.

When you are authoring Web pages, you can set properties at design time in an object's OBJECT tags. You can set properties at run time in your scripting code (for instance, VBScript).


run time <definition>

run time

The time during which an application is running. During run time, you can interact with an application. In contrast, during design time, you create objects and modify their design.

When you are authoring Web pages, you can set properties at design time in an object's OBJECT tags in HTML. You can set properties at run time in your scripting code (for instance, VBScript).


business rule <definition>

business rule

The combination of validation edits, logon verifications, database lookups, policies, and algorithmic transformations that constitute an enterprise's way of doing business. Also known as business logic.


marshaling <definition>

marshaling

The process of packaging and sending interface method parameters across thread or process boundaries.


Ensuring Sufficient TempDB Space

If errors occur while handling Recordset objects that need processing space on SQL Server, you may need to increase the size of the TempDB. (Some queries require temporary processing space; for example, a query with an ORDER BY clause requires a sort of the Recordset, which requires some temporary space.)

Important Read through this procedure before performing the actions because it isn't as easy to shrink a device once it is expanded.

To increase the TempDB space on SQL Server

  1. Start Microsoft® SQL Server Enterprise Manager, open the tree for the Server, and then open the Database Devices tree.

  2. Select a (physical) device to expand, such as Master, and double-click the device to open the Edit Database Device dialog box.

    This dialog box shows how much space the current databases are using.

  3. In the Size scroll box, increase the device to the desired amount (for example, 50 megabytes (MB) of hard disk space).

  4. Click Change Now to increase the amount of space to which the (logical) TempDB can expand.

  5. Open the Databases tree on the server, and then double-click TempDB to open the Edit Database dialog box. The Database tab lists the amount of space currently allocated to TempDB (Data Size). By default, this is 2 MB.

  6. Under the Size group, click Expand. The graphs show the available and allocated space on each of the physical devices. The bars in maroon color represent available space.

  7. Select a Log Device, such as Master, to display the available size in the Size (MB) box.

  8. Click Expand Now to allocate that space to the TempDB database.

    The Edit Database dialog box displays the new allocated size for TempDB.

See Also For more information about this topic, search the Microsoft SQL Server Enterprise Manager Help file for "Expand Database dialog box."


Configuring the SQL Server Computer to Use TCP/IP Sockets

On the SQL Server computer, run the SQL Server Setup program so that interactions with the data source use the TCP/IP Socket network library.

To specify the TCP/IP Socket network library on the SQL Server computer

  1. From the Start menu, point to Programs, point to Microsoft SQL Server 6.5, then click SQL Setup.

  2. Click Continue twice. The Microsoft SQL Server 6.5—Options dialog box appears.

  3. Select Change Network Support, and click Continue.

  4. Make sure the TCP/IP Sockets check box is selected, and click OK.

  5. Click Continue to finish, and exit setup.


Minimizing Log File Space Usage

A log file may fill quickly (thus halting the server) if there is a large volume of activity on a SQL Server database. You can set the log file to Truncate on Checkpoint to significantly extend the life of the log file for a database.

To enable Truncate on Checkpoint

  1. Run Microsoft SQL Server Enterprise Manager.

  2. Open the tree for the Server.

  3. Open the Databases tree.

  4. Double-click the name of the database on which this feature will be enabled.

  5. On the Database tab, click Truncate.

  6. On the Options tab, select Truncate Log on Checkpoint, and then click OK.

See Also For more information about the Truncate on Checkpoint feature, see the Microsoft SQL Server documentation.


Connection Pooling Options

If you're using an ODBC data source, you can use the Connection Pooling option in Internet Information Server (IIS) to achieve high performance handling of client load. Connection Pooling is a resource manager for connections, maintaining the open state on frequently used connections.

To enable Connection Pooling, refer to the Internet Information Server documentation.

Please note that enabling Connection Pooling may subject the Web server to other restrictions, as noted in the Microsoft Internet Information Server documentation.


Displaying Data Through a Bound Control

Bound controls are the data-aware controls through which you access information in a database. When a control is bound to the RDS.DataControl object, Remote Data Service applies field values from the current database record to that control. In turn, the control displays data to you and accepts your changes.

With Internet Explorer 4.0, you can bind to simple HTML controls. Other ActiveX data-aware controls are available from third parties, such as Sheridan.

Two relationships are key to data binding with Internet Explorer 4.0: source and consumer. Data consumers specify binding by referencing the data source to which they are bound. To achieve this, your data consumers (controls such as text boxes or grids) specify the source of the data and the type of the data being bound.

Most bound controls are characterized by the following data-aware parameters of the <OBJECT> tag. These parameters are the HTML data-binding extensions available with Internet Explorer 4.0.

Parameter | Description
DATASRC | Indicates the data source (RDS.DataControl object) for data binding.
DATAFLD | Indicates a column of a data set.
DATAFORMATAS | (Optional) Indicates the type of data being bound.

You can have more than one bound control for a particular field, but you don't need to provide a bound control for each field in the table.

When you access your Web page front end, the RDS.DataControl works together with the database to give you access to a Recordset. You can then navigate the Recordset with navigation buttons that use the RDS.DataControl object's MoveFirst, MoveLast, MoveNext, and MovePrevious methods. You can also send updates to the database by using the RDS.DataControl object's SubmitChanges method.


Microsoft Transaction Server Resource Dispensers

In a three-tiered environment, clients can share database connections if you use Microsoft Transaction Server on the middle tier. You can use the RDSServer.DataFactory object or create an ActiveX component DLL that can set up ODBC connections for clients to share. The sharing mechanism comes into play when you run the RDSServer.DataFactory or custom business object in the Transaction Server run-time environment. Instead of using thousands of database connections, you could get away with hundreds, still supporting thousands of clients. This is a feature of the ODBC resource dispenser in Microsoft Transaction Server.

Running Business Objects in Microsoft Transaction Server

Business objects can be executable files (.exe) or dynamic-link libraries (.dll). The configuration you use to run the business object depends on whether the object is a .dll or .exe file:

  • Business objects created as .exe files can be called through DCOM. If these business objects are used through Internet Information Server (IIS), they are subject to additional marshaling of data, which will slow client performance.

  • Business objects created as .dll files can be used via IIS (and therefore HTTP), and over DCOM only via Microsoft Transaction Server. Business object DLLs will need to be registered on the IIS computer to give you accessibility via IIS. The RDSServer.DataFactory object is a DLL that is the default business object provided by Remote Data Service, and it is also subject to the conditions in this section. (For steps on how to configure a DLL to run on DCOM, see the next section, "Enabling a DLL to Run on DCOM.")

By running the RDSServer.DataFactory object or your custom business object in the MTS run-time environment, you can also boost your performance and scalability by using the MTS resource dispenser. Because these business objects call ADO, which indirectly calls ODBC, you can take advantage of the MTS ODBC resource dispenser.

Resource dispensers automatically pool and recycle resources. Therefore, when RDSServer.DataFactory or your custom business object releases a database connection, the connection is returned to a pool. When a method is called to create a connection again, it requests the same database connection. Instead of creating a new connection, the ODBC resource dispenser recycles the pooled connection, which saves time and server resources.

Note When business objects on the middle tier are implemented as Microsoft Transaction Server components (using GetObjectContext, SetComplete, and SetAbort), they can use Transaction Server context objects to maintain their state across multiple client calls. This scenario is possible with DCOM, which is typically implemented between trusted clients and servers (an intranet). In this case, the RDS.DataSpace object and CreateObject method on the client side are replaced by the transaction context object and CreateInstance method (provided by the ITransactionContext interface), implemented by Microsoft Transaction Server.


Security and Your Web Server

If you use the RDSServer.DataFactory object on your Internet Web server, remember that doing so creates a potential security risk. External users who obtain valid data source name (DSN), user ID, and password information could write pages to send any query to that data source. If you want more restricted access to a data source, one option is to unregister and delete the RDSServer.DataFactory object (msadcf.dll), and instead use custom business objects with hard-coded queries. The next section describes how to do this.

Client Impersonation and Security

If the Password Authentication property for your IIS Web server is set to Windows NT Challenge/Response, then business objects are invoked under the client's security context. This is a new feature in RDS 1.5 that allows Client Impersonation over HTTP. When working in this mode, the login to the Web server (IIS) is not anonymous but uses the user ID and password the client computer is running under. If the ODBC DSNs are set up to use Trusted Connection, then access to databases such as SQL Server also happens under the client's security context. But this only works if the database is on the same computer as the IIS; the client credentials cannot be carried over to yet another computer.

For example, a client, John Doe, with userid="JohnD" and password="secret" is logged on a client computer. He runs a browser-based application that needs to access the RDSServer.DataFactory object to create an ADOR.Recordset by executing an SQL query on the "MyServer" computer running IIS. MyServer is set up to use "Windows NT Challenge/Response" for Password Authentication, its ODBC DSN has "Use Trusted Connection" selected, and the server also contains the SQL Server data source. When a request is received on the Web server, it asks the client for the user ID and password. Thus, the request is logged on MyServer as coming from "JohnD"/"Secret" instead of IUSER_MyServer (which is the default when Anonymous Password Authentication is on). Similarly, when logging on to SQL Server, "JohnD"/"Secret" is used.

Consequently, the IIS NT Challenge/Response authentication mode allows HTML pages to be created without the user being explicitly prompted for the user ID and password information needed to log on to the database. If the IIS Basic Authentication were being used, then this also would be required.

Password Authentication

RDS can communicate with an IIS Web server running in any one of the three Password Authentication modes: Anonymous, Basic, or NT Challenge/Response. These settings define how a Web server controls access through it, such as requiring that a client computer have explicit access privileges on the NT Web server.


Configuring the Web Server to Use TCP/IP Sockets

There are two options for configuring the Web server to use TCP/IP Sockets. What you do depends on whether all SQL Servers are accessed from the Web server, or only a specific SQL Server is accessed from the Web server.

If all SQL Servers are accessed from the Web server, you need to run the SQL Server Client Configuration Utility on the Web server computer. The following steps change the default network library for all SQL Server connections made from this IIS Web server to use the TCP/IP Sockets network library.

To configure the Web server (all SQL Servers)

  1. From the Start menu, point to Programs, point to Microsoft SQL Server 6.5, and then click SQL Client Configuration Utility.

  2. Select the Net Library tab.

  3. In the Default Network box, select TCP/IP Sockets.

  4. Click Done to save changes and exit the utility.

If a specific SQL Server is accessed from a Web server, you need to run the SQL Server Client Configuration Utility on the Web server computer. To change the network library for a specific SQL Server connection, on the Web server computer, configure the SQL Server Client software as follows.

To configure the Web server (a specific SQL Server)

  1. From the Start menu, point to Programs, point to Microsoft SQL Server 6.5, and then click SQL Client Configuration Utility.

  2. Select the Advanced tab.

  3. In the Server box, type the name of the server to connect to using TCP/IP Sockets.

  4. In the DLL Name box, select TCP/IP Sockets.

  5. Click Add/Modify. All data sources pointing to this server will now use TCP/IP Sockets.

  6. Click Done.


Performance and Stability with Connection Pooling

To ensure that connection pooling is stable and provides additional performance gains, you must configure Microsoft SQL Server to use the TCP/IP Socket network library.

To do this, you need to:

  • Configure the SQL Server computer to use TCP/IP Sockets.

  • Configure the Web server to use TCP/IP Sockets.