Today's lesson covers three important topics in OLE DB application development: properties, transactions, and the Index object. You have already learned about OLE DB objects and have used their methods, but you haven't yet discovered how to change the state of an object. Today you will learn how to use properties to control the state of an object, or in other words, how to set and retrieve property values of OLE DB objects by using special interfaces. The other major topics for today are the Transaction object and the Index object.
Today you will
Properties specify the attributes of an OLE DB object and can determine how the object behaves. Some properties can only be read, whereas others can be read and written. Properties are identified by globally unique identifier (GUID) constants and grouped according to the object on which they function. The following objects have special properties: Columns, DataSource, DataSource initialization objects, Index, Rowset, Session, and Table. Today's explanation of properties begins by discussing how to retrieve a property value.
Most OLE DB objects use the GetProperties method to retrieve
property values. Table 20.1 summarizes the methods used by each
OLE DB object to access its properties. Because most objects use
the GetProperties method, this section focuses on that
mechanism for retrieving property values.
Columns | IcolumnsRowset | GetColumnsRowset |
DataSource | IDBProperties | GetProperties |
Index | IRowsetIndex | GetIndexInfo |
Rowset | IRowsetInfo
IcommandInfo IcommandProperties | GetProperties GetProperties GetProperties |
Session | IsessionProperties | GetProperties |
Table | ITableDefinition | CreateTable |
The GetProperties method is defined as follows:
GetProperties(ULONG lNumPropIDs, DBPROPIDSET rPropIDs[], ULONG lNumPropSets, DBPROPSET **prPropSets);
The lNumPropIDs parameter specifies the number of elements in the rPropIDs array. The rPropIDs array contains a collection of DBPROPIDSET structures that specify the collection of properties for which you want to see values. The DBPROPIDSET structure is defined as follows:
typedef struct tagDBPROPIDSET { DBPROPID *rgPropertyIDs; ULONG cPropertyIDs; GUID guidPropertySet; } DBPROPIDSET;
The rgPropertyIDs field defines an array of Property
IDs. That is, the DBPROPIDSET holds a collection
of property IDs, and the GetProperties method actually
takes a collection of DBPROPIDSET structures, which in
themselves contain a collection of property IDs. You will typically
define a single DBPROPIDSET structure, which contains
a collection of the property IDs you want to retrieve. The cPropertyIDs
field defines the number of elements in the rgPropertyIDs
array. The guidPropertySet field holds a GUID that defines
the property group to which the properties in the rgPropertyIDs
array belong. Table 20.2 defines the group GUID constants and
the OLE DB object they define.
Column | DBPROPSET_COLUMN |
DataSource | DBPROPSET_DATASOURCE |
DataSource (information) | DBPROPSET_DATASOURCEINFO |
DataSource (initialization) | DBPROPSET_DBINIT |
Index | DBPROPSET_INDEX |
Rowset | DBPROPSET_ROWSET |
Session | DBPROPSET_SESSION |
Table |
DBPROPSET_TABLE |
To retrieve a property value, you must create the DBPROPIDSET structure that contains the properties you want to retrieve. On return, the prPropSet parameter contains a pointer to an array of DBPROPSET structures, and each array element contains a collection of property values. The DBPROPSET structure is defined as the following:
typedef struct tagDBPROPSET { DBPROP *rgProperties; ULONG cProperties; GUID guidPropertySet; } DBPROPSET;
NOTE |
The memory used by the prPropSet parameter is allocated by the call to the GetProperties method. The Free method of the Imalloc interface should be used to deallocate this memory when it is no longer required. You can also use the CoTaskMemFree API call if you don't have a pointer to the IMalloc interface available. It saves several lines of code, and it's functionally equivalent. |
The rgProperties field defines an array of DBPROP structures. The DBPROP structures hold the actual property values. The cProperties field defines the number of elements in the rgProperties array. The guidProperties defines the property group to which the properties in the rgProperties array belong. The DBPROP structure, which holds the actual property values, is defined as follows:
typedef struct tagDBPROP { DBPROPID dwPropertyID; DBPROPOPTIONS dwOptions; DBPROPSTATUS dwStatus; DBID colid; VARIANT vValue; } DBPROP;
The dwPropertyID field defines the property ID; it is
defined as a simple DWORD type. The dwOptions
field determines whether the property is optional or required
and what to do if much of processing is required to set the value.
The dwOptions field is a combination of the constants:
DBPROPOPTIONS_REQUIRED if the value is required and DBPROPOPTIONS_SETIFCHEAP
to determine whether it should be set if it takes much processing.
The dwStatus determines the status of the property. Table
20.3 defines the possible values of the dwStatus field
and their meanings. The colid field defines the column
for which this property is defined. The colid is a DBID
type structure, as you might recall from Day 18, "Querying a Data Source."
Finally the vValue field defines the value of the property;
it's defined as a standard C++ VARIANT type.
DBPROPSTATUS_OK | The property's value has been successfully set. |
DBPROPSTATUS_BADCOLUMN | The colid field doesn't define a valid field. |
DBPROPSTATUS_BADOPTION | The dwOptions field contained an illegal value. |
DBPROPSTATUS_BADVALUE | The vValue field contained an illegal value. |
DBPROPSTATUS_CONFLICTING | Changing the value of this property would result in a conflicting state; the operation was performed. |
Status Value | Description |
DBPROPSTATUS_NOTALLSETTABLE | When trying to set a property that applies to a set of columns, the operation was denied because it couldn't be set for all columns. |
DBPROPSTATUS_NOTSET | The DBPROPOPTIONS_SETIFCHEAP option prevented the property from being set. |
DBPROPSTATUS_NOTSETTABLE | You can't set the value of a read-only property. |
DBPROPSTATUS_NOTSUPPORTED | The data provider doesn't support the specified property. |
Now that you have the background information you need in order to use the GetProperties method, you can construct the appropriate structures to retrieve a property's value and interpret the results. You need to define one structure to define the property ID you want to retrieve, and you need to define one structure to return the actual property values. (A listing and descriptions of OLE DB object property IDs appear later in this lesson.)
In the Day 18 compendium of the
SQL command language, I discussed the use of the GetProperties
method of the IDBProperties interface to determine whether
the data provider supported the SQL command language. The property
ID to check for SQL support is DPROP_SQLSUPPORT. This
property is represented as a long integer, which determines the
level of SQL support provided by the data provider. Listing 20.1
demonstrates how to retrieve the DBPROP_SQLSUPPORT property
of the DataSource object to determine the level of SQL
support provided by the data provider. Note that for brevity,
the code in Listing 20.1 doesn't check the return value from GetProperties.
Without testing the HRESULT, you have no way of knowing
whether the properties were actually returned. In your production
code, you will need to test for the return value.
Listing 20.1 Determining the Level of SQL Support
Provided by a Data Provider, Using the DBSQL_SUPPORT Property
1: PropID = DBPROP_SQLSUPPORT; // SQL Support 2: // Interface 3: PropIDSet.rgPropertyIDs = &PropID; // Specify the 4: // property ID 5: PropIDSet.cPropertyIDs = 1; // Only one Property ID 6: PropIDSet.guidPropertySet = DBPROPSET_DATASOURCEINFO; // It's a DataSource 7: // object Property 8: 9: // Retrieve the Properties 10: pIDBProperties->GetProperties(1, &PropIDSet, &lNumProps, &pPropSet); 11: 12: // Interpret the property value 13: if(pPropSet->rgProperties->vValue.lVal & DBPROPVAL_SQL_NONE) { 14: cout << "SQL Commands are not supported\n"; 15: }; 16: 17: if(pPropSet->rgProperties->vValue.lVal & DBPROPVAL_SQL_ODBC_MINIMUM) { 18: cout << "ODBC Minimum SQL Commands supported\n"; 19: }; 20: 21: if(pPropSet->rgProperties->vValue.lVal & DBPROPVAL_SQL_ODBC_CORE) { 22: cout << "ODBC Core SQL Commands supported\n"; 23: }; 24: 25: if(pPropSet->rgProperties->vValue.lVal & DBPROPVAL_SQL_ODBC_EXTENDED) { 26: cout << "ODBC Extended SQL Commands supported\n"; 27: }; 28: 29: if(pPropSet->rgProperties->vValue.lVal & DBPROPVAL_SQL_ANSI92_ENTRY) { 30: cout << "ANSI 92 Entry SQL Commands supported\n"; 31: }; 32: 33: if(pPropSet->rgProperties->vValue.lVal & DBPROPVAL_SQL_FIPS_TRANSITIONAL) { 34: cout << "FIPS Transitional SQL Commands supported\n"; 35: }; 36: 37: if(pPropSet->rgProperties->vValue.lVal & DBPROPVAL_SQL_ANSI92_INTERMEDIATE) { 38: cout << "ANSI 92 Intermediate SQL Commands supported\n"; 39: }; 40: 41: if(pPropSet->rgProperties->vValue.lVal & DBPROPVAL_SQL_ANSI92_FULL) { 42: cout << "ANSI 92 Full SQL Commands supported\n"; 43: }; 44: 45: if(pPropSet->rgProperties->vValue.lVal & DBPROPVAL_SQL_ANSI89_IEF) { 46: cout << "ANSI 89 Integrity Enhancement Facility SQL Commands supported\n"; 47: };
NOTE |
OLE DB also provides the GetPropertyInfo and GetCreationProperties methods to retrieve additional information about the properties that each object makes available. |
To establish a connection to the DataSource object by using the OLE DB ODBC provider, you used the SetProperties method (refer to Day 18) to specify the required ODBC connection parameters. The primary method that OLE DB objects use to specify property values is the SetProperties method. The SetProperties method is defined as follows:
SetProperties(ULONG cPropertySets, DBPROPSET rgPropertySets[]);
The cPropertySets parameter specifies the number of elements in the rgPropertySets array. This array contains a collection of property values. The rgPropertySets parameter is a DBPROPSET type, discussed earlier today. To set the value of a property, you need to create the rgPropertySets array and call the SetProperties method.
TIP |
On return from the SetProperties method, check the status of each property to determine whether it was set properly. |
Property status values are listed in Table 20.3. Table 20.4 lists
the methods that each OLE DB object uses in order to specify property
values.
Columns | IColumnsRowset | AddColumn |
DataSource | IDBProperties | SetProperties |
Index | IRowsetIndex | GetIndexInfo |
Rowset | IRowsetInfo | GetProperties |
ICommandProperties | SetProperties | |
Session | ISessionProperties | SetProperties |
Table | ITableDefinition | CreateTable |
Now that you understand the structures involved in specifying
a property, you can specify a property value and check the status
of the property set operation. Listing 20.2 demonstrates how to
use the DBPROP_INIT_TIMEOUT property. (The complete source
code is on the CD-ROM.) This property is part of the DBPROPSET_DBINIT
group and is used to specify the number of seconds to wait while
a connection to the data source is established. Note that for
brevity, the code in Listing 20.2 doesn't check the return values.
In your production code, you will need to test for the return
values.
Listing 20.2 How to Use the SETPROPERTIES
Method to Set the DBPROP_INIT_TIMEOUT
Property
1: // Obtain Access To The OLE DB - ODBC Provider 2: CoCreateInstance(CLSID_MSDASQL, NULL, CLSCTX_INPROC_SERVER, 3: IID_IDBInitialize, (void **) &pIDBInitialize); 4: 5: // Initialize the property values 6: VariantInit(&InitProperties[0].vValue); 7: InitProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED; 8: InitProperties[0].colid = DB_NULLID; 9: InitProperties[0].dwPropertyID = DBPROP_INIT_TIMEOUT; 10: InitProperties[0].vValue.vt = VT_I4; 11: 12: // Set the timeout value to 90 seconds 13: InitProperties[0].vValue.lVal = 90; 14: 15: // Specify the Property Set 16: rgInitPropSet[0].guidPropertySet = DBPROPSET_DBINIT; 17: rgInitPropSet[0].cProperties = 1; 18: rgInitPropSet[0].rgProperties = InitProperties; 19: 20: // set initialization properties 21: pIDBInitialize->QueryInterface(IID_IDBProperties, (void **)&pIDBProperties); 22: pIDBProperties->SetProperties(1,rgInitPropSet); 23: // Remember to release pIDBInitialize and pIDBProperties.
Table 20.5 lists all the properties that OLE DB objects support. This table lists each property ID and its variant type. An asterisk (*) after a property name signifies that it is a read-only property.
NOTE |
Certain data providers might provide their own set of properties, so check the data provider documentation for more information. For example, the OLE DB ODBC data provider supports its own set of properties. These properties are part of two OLE DB ODBC provider-specific groups: DBPROPSET_PROVDERDATASOURCEINFO and DBPROPSET_PROVIDERROWSET. |
DBPROP_COL_AUTOINCREMENT | A VT_BOOL type property. If it's true, the column will automatically increment. |
DBPROP_COL_DEFAULT | A property of any type. It specifies the default value of a column. |
DBPROP_COL_DESCRIPTION | A VT_STR type property. It specifies a column description. |
DBPROP_COL_FIXEDLENGTH | A VT_BOOL type property. If it's true, the column has a fixed length. |
DBPROP_COL_NULLABLE | A VT_BOOL type property. If it's true, the column can contain NULL values. |
DBPROP_COL_PRIMARYKEY | A VT_BOOL type property. If it's true, this column is part of the primary key. |
DBPROP_COL_UNIQUE | A VT_BOOL type property. If it's true, this column must be unique. |
DBPROP_CURRENTCATALOG | A VT_BSTR type property. It names the current data source catalog. |
DBPROP_ACTIVESESSIONS * | A VT_I4 type property. It specifies the maximum number of sessions; if 0, sessions are unlimited. |
DBPROP_ASYNCTXNABORT * | A VT_BOOL type property. If it's true, transactions can be aborted asynchronously. |
DBPROP_ASYNCTXNCOMMIT * | A VT_BOOL type. If it's true, transactions can be committed asynchronously. |
DBPROP_BYREFACCESSORS * | A VT_BOOL type property. If it's true, the data source can accept parameters passed by reference (as pointers). |
DBPROP_CATALOGLOCATION * | A VT_I4 type property. It returns DBPROPVAL_CL_START if the catalog name is at the beginning or DBPROPVAL_CL_END if it's at the end. |
DBPROP_CATALOGTERM * | A VT_BSTR type property. It specifies the name that a data source uses for a catalog. |
DBPROP_CATALOGUSAGE * | A VT_I4 type property. It's used to determine where catalog names are supported. |
DBPROP_COLUMNDEFINITION * | A VT_I4 type property. It's used to determine valid column states. |
DBPROP_CONCATNULLBEHAVIOR | A VT_I4 type property. It determines how NULL strings are handled when added to other character strings. |
DBPROP_DATASOURCENAME * | A VT_BSTR type property. It specifies the name of the data source. |
DBPROP_DATASOURCEREADONLY * | A VT_BOOL type property. If it's true, the data source is read-only. |
DBPROP_DBMSNAME * | A VT_BSTR type property. It specifies the name of the data provider. |
DBPROP_DBMSVER * | A VT_BSTR type property. It specifies the version of the data provider. |
DBPROP_DSOTHREADMODEL * | A VT_I4 type property. It specifies the threading model supported by the data provider. |
DBPROP_GROUPBY * | A VT_I4 type property. It specifies how the GROUP BY clause functions. |
DBPROP_HETEROGENEOUSTABLES * | A VT_I4 type property. It specifies whether joins can be performed across providers or catalogs. |
DBPROP_IDENTIFIERCASE * | A VT_I4 type parameter. It specifies whether the case of identifiers is significant. |
DBPROP_MAXINDEXSIZE * | A VT_I4 type parameter. It specifies the maximum size of a key; if 0, there is no limit. |
DBPROP_MAXROWSIZE * | A VT_I4 type parameter. It specifies the maximum length of a row; if 0, there is no limit. |
DBPROP_MAXROWSIZEINCLUDESBLOB * | A VT_BOOL type parameter. If it's true, the DBPROP_MAXROWSIZE property includes BLOB fields. |
DBPROP_MAXTABLESINSELECT * | A VT_I4 type parameter. It specifies the maximum number of tables that can be used in a SELECT statement. |
DBPROP_MULTIPLEPARAMSETS * | A VT_BOOL type parameter. If it's true, the data source supports multiple parameter sets. |
DBPROP_MULTIPLERESULTS * | A VT_I4 type parameter. It specifies whether the data source can support multiple resultsets. |
DBPROP_MULTIPLESTORAGEOBJECTS * | A VT_BOOL type parameter. If it's true, the data source can open multiple objects at the same time. |
DBPROP_MULTITABLEUPDATE * | A VT_BOOL type parameter. If it's true, the data source can update row sets that contain multiple tables. |
DBPROP_NULLCOLLATION * | A VT_I4 type parameter. It specifies how NULL values are handled when sorting. |
DBPROP_OLEOBJECTS * | A VT_I4 type parameter. It specifies whether BLOB and OLE objects can be accessed through streaming or storage objects. |
DBPROP_ORDERBYCOLUMNSINSELECT * | A VT_BOOL type parameter. If it's true, the columns specified in an ORDER BY clause must be part of the SELECT statement. |
DBPROP_OUTPUTPARAMETERAVAILABILITY * | A VT_I4 type parameter. It specifies when output parameters can be accessed. |
DBPROP_PERSISTENTIDTYPE * | A VT_I4 type parameter. It specifies the type of persistent DBID supported by a data source. |
DBPROP_PREPAREABORTBEHAVIOR * | A VT_I4 type parameter. It specifies what happens to a prepared statement when it's aborted in a transaction. |
DBPROP_PREPARECOMMITBEHAVIOR * | A VT_I4 type parameter. It specifies what happens to a prepared statement when it's committed in a transaction. |
DBPROP_PROCEDURETERM * | A VT_BSTR type parameter. It specifies what the data source calls a procedure. |
DBPROP_PROVIDERNAME * | A VT_BSTR type parameter. It specifies the executable filename of the provider. |
DBPROP_PROVIDEROLEDBVER * | A VT_BSTR type parameter. It specifies the OLE DB specification version supported by the provider. |
DBPROP_PROVIDERVER * | A VT_BSTR type parameter. It specifies the version of the data provider. |
DBPROP_QUOTEDIDENTIFIERCASE * | A VT_I4 type parameter. It specifies how case is handled for quoted identifiers. |
DBPROP_ROWSETCONVERSIONSONCOMMAND * | A VT_BOOL type parameter. If it's true, an inquiry can be made about conversions on the row sets of a command. |
DBPROP_SCHEMATERM * | A VT_BSTR type parameter. It specifies the term used by the data source for a schema. |
DBPROP_SCHEMAUSAGE * | A VT_I4 type parameter. It specifies how schema names can be used in commands. |
DBPROP_SQLSUPPORT * | A VT_I4 type parameter. It specifies the level of SQL supported by the data source. |
DBPROP_STRUCTUREDSTORAGE * | A VT_I4 type parameter. It specifies streaming interfaces supported for row sets. |
DBPROP_SUBQUERIES * | A VT_I4 type parameter. It specifies whether subqueries are supported in commands. |
DBPROP_SUPPORTEDTXNDDL * | A VT_I4 type parameter. It specifies whether data definition commands are supported in transactions. |
DBPROP_SUPPORTEDTXNISOLEVELS * | A VT_I4 type parameter. It specifies the transaction isolation levels supported by the data source. |
DBPROP_SUPPORTEDTXNISORETAIN * | A VT_I4 type parameter. It specifies the retention levels supported by transaction isolation. |
DBPROP_TABLETERM * | A VT_BSTR type parameter. It specifies the term used by the data source for tables. |
DBPROP_USERNAME * | A VT_BSTR type parameter. It specifies the name of the user attached to the data source. |
DBPROP_AUTH_CACHE_AUTHINFO | A VT_BOOL type parameter. If it's true, the data source can store password and user information in a local cache. |
DBPROP_AUTH_ENCRYPTPASSWORD | A VT_BOOL type parameter. If it's true, the data source requires the password to be sent in an encrypted form. |
DBPROP_AUTH_INTEGRATED | A VT_BSTR type parameter. It specifies the name of the authentication service to be used. |
DBPROP_AUTH_MASK_PASSWORD | A VT_BOOL type parameter. If it's true, the password must be masked before it's sent to the data source. |
DBPROP_AUTH_PASSWORD | A VT_BSTR type parameter. This is the password used for authentication (can be masked). |
DBPROP_AUTH_PERSISTENCRYPTED | A VT_BOOL type parameter. If it's true, the data source must save authentication information. |
DBPROP_AUTH_PERSIST_SENSITIVEAUTHINFO | A VT_BOOL type parameter. If it's true, the data source is allowed to persist authentication information. |
DBPROP_AUTH_USERID | A VT_BSTR type parameter. It specifies the username used to connect to the data source. |
DBPROP_INIT_DATASOURCE | A VT_BSTR type parameter. This is the name of the data source to connect to. |
DBPROP_INIT_HWND | A VT_I4 type parameter. This is the window handle used if a prompt window must be displayed when accessing the data source. |
DBPROP_INIT_IMPERSONATIONLEVEL | A VT_I4 type parameter. It specifies the impersonation level used for remote procedure calls. |
DBPROP_INIT_LCID | A VT_I4 type parameter. It specifies the location identifier. |
DBPROP_INIT_LOCATION | A VT_BSTR type parameter. It specifies the location of the data source (that is, the name of the server). |
DBPROP_INIT_MODE | A VT_I4 type parameter. It specifies the read, write, share access level to the data source. |
DBPROP_INIT_PROMPT | A VT_I4 type parameter. It specifies whether a prompt should be displayed for user/data source information if it's required when connecting to a data source. |
DBPROP_INIT_PROTECTION_LEVEL | A VT_I4 type parameter. It specifies the remote procedure call connection level used. |
DBPROP_INIT_PROVIDERSTRING | A VT_BSTR type parameter. It specifies provider-specific connection parameters. |
DBPROP_INIT_TIMEOUT | A VT_I4 type parameter. It specifies the amount of time to wait for a connection to complete. |
DBPROP_INDEX_AUTOUPDATE | A VT_BOOL type parameter. If it's true, the index is automatically updated whenever a change is made. |
DBPROP_INDEX_CLUSTERED | A VT_BOOL type parameter. If it's true, the index uses clustering. |
DBPROP_INDEX_FILLFACTOR | A VT_I4 type parameter. It specifies the B+tree fill factor for the index. |
DBPROP_INDEX_INITIALSIZE | A VT_I4 type parameter. It specifies the initial size to allocate for the index. |
DBPROP_INDEX_NULLCOLLATION | A VT_I4 type parameter. It specifies how NULL values are treated in the sorting order. |
DBPROP_INDEX_NULLS | A VT_I4 type parameter. It specifies whether an index can use NULL values. |
DBPROP_INDEX_PRIMARYKEY | A VT_BOOL type parameter. If it's true, this index is based on the primary key. |
DBPROP_INDEX_SORTBOOKMARKS | A VT_BOOL type parameter. If it's true, the index sorts bookmarks. |
DBPROP_INDEX_TEMPINDEX | A VT_BOOL type parameter. If it's true, the index is temporary. |
DBPROP_INDEX_TYPE | A VT_I4 type parameter. It specifies the type of index mechanisms used by the data source. |
DBPROP_INDEX_UNIQUE | A VT_BOOL type parameter. If it's true, the index keys must be unique. |
DBPROP_ABORTPRESERV | A VT_BOOL type parameter. If it's true, the row set is preserved even after an aborted transaction. |
DBPROP_APPENDONLY | A VT_BOOL type parameter. If it's true, rows can only be added to the row set. You use this when creating new tables. |
DBPROP_BLOCKINGSTORAGEOBJECTS | A VT_BOOL type parameter. If it's true, storage objects could prevent other operations. |
DBPROP_BOOKMARKS | A VT_BOOL type parameter. If it's true, bookmarks can be used by the row set. |
DBPROP_BOOKMARKSKIPPED | A VT_BOOL type parameter. If it's true, the GetRowsAt method can skip deleted bookmark rows. |
DBPROP_BOOKMARKTYPE | A VT_I4 type parameter. It specifies the type of bookmarks used: numeric or key. |
DBPROP_CACHEDEFERRED | A VT_BOOL type parameter. If it's true, deferred columns can be cached. |
DBPROP_CANFETCHBACKWARDS | A VT_BOOL type parameter. If it's true, methods used to get rows can retrieve rows before the current row. |
DBPROP_CANHOLDROWS | A VT_BOOL type parameter. If it's true, additional rows can be fetched when changes are pending. |
DBPROP_CANSCROLLBACKWARDS | A VT_BOOL type parameter. If it's true, you can retrieve rows before the current row. |
DBPROP_CHANGEINSERTEDROWS | A VT_BOOL type parameter. If it's true, you can make modifications to rows that have been added to the row set. |
DBPROP_COLUMNRESTRICT * | A VT_BOOL type parameter. If it's true, access can be restricted at the column level. |
DBPROP_COMMANDTIMEOUT | A VT_I4 type parameter. It specifies the amount of time before a command times out. |
DBPROP_COMMITPRESERVE | A VT_BOOL type parameter. If it's true, the row set is preserved after the transaction has been committed. |
DBPROP_DEFERRED | A VT_BOOL type parameter. If it's true, the column data is retrieved only when the GetData method is called. |
DBPROP_DELAYSTORAGEOBJECTS | A VT_BOOL type parameter. If it's true, updates to storage objects are delayed. |
DBPROP_IAccessor | A VT_BOOL type parameter. If it's true, the row set supports the Iaccessor interface. |
DBPROP_IColumnsInfo | A VT_BOOL type parameter. If it's true, the row set supports the IcolumnsInfo interface. |
DBPROP_IColumnsRowset | A VT_BOOL type parameter. If it's true, the row set supports the IcolumnsRowset interface. |
DBPROP_IConnectionPointContainer | A VT_BOOL type parameter. If it's true, the row set supports the IconnectionPointContainer interface. |
DBPROP_IConvertType | A VT_BOOL type parameter. If it's true, the row set supports the IconvertType interface. |
DBPROP_IRowset | A VT_BOOL type parameter. If it's true, the row set supports the IRowset interface. |
DBPROP_IRowsetChange | A VT_BOOL type parameter. If it's true, the row set supports the IRowsetChAnge interface. |
DBPROP_IRowsetIdentity | A VT_BOOL type parameter. If it's true, the row set supports the IRowsetIdentity interface. |
DBPROP_IRowsetInfo | A VT_BOOL type parameter. If it's true, the row set supports the IRowsetInfo interface. |
DBPROP_IRowsetLocate | A VT_BOOL type parameter. If it's true, the row set supports the IRowsetLocate interface. |
DBPROP_IRowsetResynch | A VT_BOOL type parameter. If it's true, the row set supports the IRowsetResynch interface. |
DBPROP_IRowsetScroll | A VT_BOOL type parameter. If it's true, the row set supports the IRowsetScroll interface. |
DBPROP_IRowsetUpdate | A VT_BOOL type parameter. If it's true, the row set supports the IRowseUpdate interface. |
DBPROP_ISupportErrorInfo | A VT_BOOL type parameter. If it's true, the row set supports the IsupportErrorInfo interface. |
DBPROP_ILockBytes | A VT_BOOL type parameter. If it's true, the row set supports the ILockBytes storage interface. |
DBPROP_ISequentialStream | A VT_BOOL type parameter. If it's true, the row set supports the IsequentialStream storage interface. |
DBPROP_IStorage | A VT_BOOL type parameter. If it's true, the row set supports the Istorage storage interface. |
DBPROP_IStream | A VT_BOOL type parameter. If it's true, the row set supports the IStream storage interface. |
DBPROP_IMMOBILEROWS | A VT_BOOL type parameter. If it's true, updated rows will not be reordered. |
DBPROP_LITERALBOOKMARKS | A VT_BOOL type parameter. If it's true, bookmarks can be compared in an ordinal fashion. |
DBPROP_LITERALIDENTITY * | A VT_BOOL type parameter. If it's true, row handles can be compared to see whether they are the same. |
DBPROP_MAXOPENROWS * | A VT_I4 type parameter. It specifies the maximum number of rows that can be opened at once; if 0, there is no limit. |
DBPROP_MAXPENDINGROWS * | A VT_I4 type parameter. It specifies the maximum number of rows that can simultaneously have pending updates. |
DBPROP_MAXROWS * | A VT_I4 type parameter. It specifies the maximum number of rows that can be in a row set, and if 0, there is no limit. |
DBPROP_MAYWRITECOLUMN | A VT_BOOL type parameter. If it's true, a column is writable. |
DBPROP_MEMORYUSAGE | A VT_I4 type parameter. It specifies the percentage of memory that a row set can use. If it's 0, there is no limit. |
DBPROP_NOTIFICATIONGRANULARITY | A VT_I4 type parameter. It specifies when notification occurs. |
DBPROP_NOTIFICATIONPHASES * | A VT_I4 type parameter. It specifies when notifications are supported by the data provider. |
DBPROP_NOTIFYCOLUMNSET * | A VT_I4 type parameter. It specifies when notifications are generated by a column set. |
DBPROP_NOTIFYROWDELETE * | A VT_I4 type parameter. It specifies when notifications are generated by a row delete. |
DBPROP_NOTIFYROWFIRSTCHANGE * | A VT_I4 type parameter. It specifies when notifications are generated by a first row change. |
DBPROP_NOTIFYROWINSERT * | A VT_I4 type parameter. It specifies when notifications are generated by an insert. |
DBPROP_NOTIFYROWRESYNCH * | A VT_I4 type parameter. It specifies when notifications are generated by a row set resynchronization. |
DBPROP_NOTIFYROWSETRELEASE * | A VT_I4 type parameter. It specifies when notifications are generated by a row set release. |
DBPROP_NOTIFYROWSETFETCHPOSITIONCHANGE* | A VT_I4 type parameter. It specifies when notifications are generated by a position change. |
DBPROP_NOTIFYROWUNDOCHANGE * | A VT_I4 type parameter. It specifies when notifications are generated by an undo of a change. |
DBPROP_NOTIFYROWUNDODELETE * | A VT_I4 type parameter. It specifies when notifications are generated by an undo of a delete. |
DBPROP_NOTIFYROWUNDOINSERT * | A VT_I4 type parameter. It specifies when notifications are generated by an undo of an insert. |
DBPROP_NOTIFYROWUPDATE * | A VT_I4 type parameter. It specifies when notifications are generated by a row update. |
DBPROP_ORDEREDBOOKMARKS | A VT_BOOL type parameter. If it's true, bookmarks can be compared in an ordinal fashion. |
DBPROP_OTHERINSERT | A VT_BOOL type parameter. If it's true, rows inserted by others into a row set can be seen when they are inserted. |
DBPROP_OTHERUPDATEDELETE | A VT_BOOL type parameter. If it's true, changes by other users are visible. |
DBPROP_OWNINSERT | A VT_BOOL type parameter. If it's true, rows inserted by this user into the row set can be seen when they are inserted. |
DBPROP_OWNUPDATEDELETE | A VT_BOOL type parameter. If it's true, rows updated or deleted by this user are visible. |
DBPROP_QUICKRESTART | A VT_BOOL type parameter. If it's true, the command that generated the row set is not re-executed when restarting. |
DBPROP_REENTRANTEVENTS * | A VT_BOOL type parameter. If it's true, reentrant events (events that can happen at the same time) are supported. |
DBPROP_REMOVEDELETED | A VT_BOOL type parameter. If it's true, rows that have been marked for deletion are not included in the row set. |
DBPROP_REPORTMULTIPLECHANGES * | A VT_BOOL type parameter. If it's true, updates and deletes on row sets that affect multiple rows can be handled. |
DBPROP_RETURNPENDINGINSERTS * | A VT_BOOL type parameter. If it's true, rows with pending changes are included in the row set. |
DBPROP_ROWRESTRICT * | A VT_BOOL type parameter. If it's true, access to rows can be specified on a row basis. |
DBPROP_ROWTHREADMODEL | A VT_I4 type parameter. It specifies the threading model used by row sets. |
DBPROP_SERVERCURSOR | A VT_BOOL type parameter. If it's true, the data source supports server-side cursors. |
DBPROP_STRONGIDENTITY * | A VT_BOOL type parameter. If it's true, row handles to newly inserted rows can be compared with existing rows in an ordinal fashion. |
DBPROP_TRANSACTEDOBJECT | A VT_BOOL type parameter. If it's true, data changes for a column must be made through transactions. |
DBPROP_UPDATABILITY | A VT_I4 type parameter. It specifies the change methods supported by the row set. |
DBPROP_SESS_AUTOCOMMITISOLEVELS | A VT_I4 type parameter. It specifies the isolation level of transactions while the Autocommit mode is active. |
DBPROP_TBL_TEMPTABLE | A VT_BOOL type parameter. If it's true, this is a temporary table. |
Now that you understand how to set and retrieve properties, and you know all the properties supported by OLE DB objects, you can begin to manipulate OLE DB objects at a higher level of detail. You will use these properties in the examples presented during the remainder of the book.
Transactions control operations on a data source and encapsulate data source operations. A transaction starts before an operation begins and can commit the operation or abort the changes an operation makes. Transactions can coordinate multiuser operations on a data source. Typically, transactions enable a user to start some data source operation and to abort this operation at a later point. The use of transactions can also significantly improve application performance. The OLE DB TTransaction CoType is defined as follows:
TTransaction { interface IConnectionPointContainer; // Required Interface interface ITransaction; // Required Interface interface ISupportErrorInfo; };
The IConnectionPointContainer and ISupportErrorInfo are discussed in previous lessons (Day 19, "Navigating the Result of a Query," and Day 17, "Accessing a Data Source with OLE DB"), and error handling is discussed in more detail on Day 21, "OLE DB Error Handling." On Day 17 you learned that the Session object supports the following Transaction-related interfaces: ITransaction, ITransactionJoin, ITransactionLocal, and ITransactionObject. I'll discuss these interfaces in detail before examining the actual mechanics of using them.
The ITransaction interface controls a transaction; it commits transactions, aborts transactions, and obtains the current transaction status. The ITransaction interface is required by the Transaction object but optional for the Session object. The ITransaction interface defines the standard IUnknown interface methods QueryInterface, AddRef, and Release. The interface also provides three additional methods: Abort, Commit, and GetTransactionInfo. These methods are defined as follows:
HRESULT Abort(BOID *pboidReason, BOOL fRetaining, BOOL fAsync); HRESULT Commit(BOOL fRetaining, DWORD grfCommitType, DWORD grfReserved); HRESULT GetTransactionInfo(XACTTRANSINFO *pTransInfo);
The Abort method aborts a series of operations performed on a data source. For logging purposes, the pboidReason parameter specifies a reason that the transaction is being aborted. This parameter is a BOID type, which is defined as follows:
typedef struct BOID { BYTE rgb[16]; };
This simply defines a 16-byte buffer. If no reason is required, the BOID_NULL constant is used. The fRetaining parameter defines the retain behavior of the abort operation, which is sometimes referred to as Autocommit mode. If true, when the abort operation is carried out and subsequent transactions are created, the abort is performed in a separate (server-side) process thread. If false, a new thread is not created to carry out the abort. The fAsync flag determines whether the operation is carried out in the background. If true, the abort command returns immediately, and the abort processing happens in the background.
CAUTION |
You must use the ITransactionOutcomeEvents interface to retrieve the results of the abort operation. If the abort is not asynchronous, you get the abort result in the return value from the Abort method call. |
The Commit method commits a series of operations performed
on a data source. The fRetaining parameter functions
in the same way as it does in the Abort method, controlling
the Autocommit mode. The grfCommitType parameter specifies
the type of commit to be performed. Table 20.6 defines and describes
the various types of commit parameters. The grfReserved
parameter is reserved for future use and should always be 0.
XACTTC_ASYNC | The commit is performed in an asynchronous mode. The Commit method returns immediately, and commit processing is carried out in the background. |
XACTTC_SYNC_PHASEONE | The Commit method returns after the first phase of the commit operation is performed. Commit methods are usually performed in two phases. |
XACTTC_SYNC_PHASETWO | The Commit method returns after the second phase of the commit operation is performed; that is, it returns when the entire operation is complete. |
XACTTC_SYNC | The commit is performed in a synchronous mode, the same as the XACTTC_SYNC_PHASETWO commit type. |
The last method of the ITransation interface, GetTransactionInfo, retrieves information about a transaction. It returns a single parameter, pTransInfo, which is a pointer to an XACTTRANSINFO structure. This structure holds information about the transaction and is defined as follows:
typedef struct tagXACTTRANSINFO { XACTUOW uow; ISOLEVEL isoLevel; ULONG isoFlags; DWORD grfTCSupported; DWORD grfRMSupported; DWORD grfTCSupportedRetaining; DWORD grfRMSupportedRetaining; } XACTRANSINFO;
The uow field defines the level at which the transaction works, typically row. The XACTUOW type is defined as the BOID type that was defined earlier. The isoLevel field specifies the isolation level (discussed in more detail shortly) of this transaction. The isoFlags field is reserved for future use and will always be 0. The grfTCSupported field specifies special transactional-level flags. The grfRMSupported, grfTCSupportedRetaining, and grfRMSupportedRetaining are reserved for future use and will currently return 0. Unless you need to determine the isolation level of a previously started transaction, the GetTransactionInfo method currently does not return much more useful information.
Just as you can use the ITransaction interface to end a transaction by committing or aborting it, you can use the ITransactionLocal interface of the Session object to begin a transaction. The ITransactionLocal interface is optional for the Session object and is supported only if the data provider supports transactions. The ITransactionLocal interface defines the standard IUnknown interface methods QueryInterface, AddRef, and Release. The interface also provides two additional methods: GetOptionsObject and StartTransaction. These methods are defined as follows:
HRESULT GetOptionsObject(ITransactionOptions **pOptionsInt); HRESULT StartTransaction(ISOLEVEL isoLevel, ULONG isoFlagsResv, ITransactionOptions *pIOptions, ULONG *lNewTransLevel);
The StartTransaction method begins a set of operations that will be enveloped by a transaction. The isoLevel parameter specifies the isolation level of the transaction. The lisoFlagResv parameter is reserved for future isolation level flags, but for now it should be 0. The pIOptions parameter specifies a pointer to the ITransactionsOption interface. If options aren't required, you can pass a NULL value. Next I will discuss how to obtain and use the ITransactionsOption interface. The lNewTransLevel parameter returns the new transaction level.
The GetOptionsObject obtains access to the ITransactionOptions interface. A pointer to this interface is returned in the pOptionsInt parameter. What options, then, can be specified for a transaction?
As I stated earlier, the ITransactionOptions interface specifies transaction-level options. This interface is accessed through the GetOptionsObject method. The ITransactionOptions interface defines the standard IUnknown interface methods QueryInterface, AddRef, and Release. Also, the interface provides two additional methods: SetOptions and GetOptions. These methods are defined as follows:
HRESULT SetOptions(XACTOPT *pOptions); HRESULT GetOptions(XACTOPT *pOptions);
The names tell us that these methods set and retrieve option values. Both methods take a single parameter, a pointer to an XACTOPT structure, which defines the transaction options. This structure is defined as follows:
typedef struct tagXACTOPT { ULONG ulTImeout; unsigned char szDescription[MAX_TRANS_DESC]; } XACTOPT;
The ulTimeout field defines the number of milliseconds that the transaction can remain open before it's automatically aborted. If this value is 0, there will be no time limit. The szDescription field defines the transaction's description.
The ITransactionObject interface obtains access to a Transaction object by specifying its level. This interface is especially useful when using nested transactions (which are discussed shortly). This interface is provided through the Session object and is available only if transactions are supported. The ITransactionObject interface defines the standard IUnknown interface methods QueryInterface, AddRef, and Release. The interface provides one more method: GetTransactionObject. This method is defined as follows:
HRESULT GetTransactionObject(ULONG lTransLevel, ITransaction **ppITrans);
The lTransLevel specifies the transaction level for which you are searching. The pITrans parameter returns the level's corresponding Transaction object.
The final transaction interface discussed today is the ITransactionJoin interface, which supports distributed transactions. This interface is provided through the Session object and is available only if transactions are supported. The ITransactionJoin interface defines the standard IUnknown interface methods QueryInterface, AddRef, and Release. The interface provides two additional methods: GetOptionsObject and JoinTransaction. These methods are defined as follows:
HRESULT GetOptionsObject(ITransactionOptions **ppITransOptions); HRESULT JoinTransaction(IUnknown *punkDistTrans, ISOLEVEL isoLevel, ULONG isoFlags, ITransactionOptions *pITransOptions);
The GetOptionsObject retrieves distributed transaction options. The JoinTransaction method joins a distributed transaction, a transaction in which multiple clients can take part. Currently, the OLE DB ODBC data provider doesn't support distributed transactions.
To create a transaction that encapsulates a series of operations,
you must first obtain access to the ITransactionLocal
interface and then use the StartTransaction method to
open the transaction. The transaction remains opened until it's
committed or aborted. Listing 20.3 demonstrates how to use the
StartTransaction method to open a database transaction.
Note that for brevity, the code in Listing 20.3 doesn't check
the return values. In your production code, be sure you test for
the return values.
Listing 20.3 How to Start a Transaction
1: // Create a Session object... 2: pIDBInitialize->QueryInterface(IID_IDBCreateSession, 3: (void **) &pCreateSession); 4: 5: // Create a Command object... 6: pCreateSession->CreateSession(NULL, IID_IDBCreateCommand, 7: (IUnknown **) &pCreateCommand); 8: 9: // Access the ICommandText interface 10: pCreateCommand->CreateCommand(NULL, IID_ICommandText, 11: (IUnknown **) &pCommandText); 12: 13: // Specify the command text 14: pCommandText->SetCommandText(DBGUID_DBSQL, wCmdString); 15: 16: // Access the Transaction Interface 17: pCreateCommand->QueryInterface(IID_ITransactionLocal, 18: (void **) &pTransLocal); 19: 20: // Start the Transaction 21: pTransLocal->StartTransaction(ISOLATIONLEVEL_SERIALIZABLE, 0, 22: NULL, &lTransLevel); 23: cout << "Transaction Level = " << lTransLevel << "\n"; 24: 25: // Execute the command 26: pCommandText->Execute(NULL, IID_IRowset, NULL, &cNumRows, 27: (IUnknown **) &pRowset); 28: // Remember to release the interface pointers.
When the StartTransaction method is called, all database
operations are saved until they are committed or aborted. When
a transaction is committed, all the operations that have been
saved are actually carried out on the data source. As you saw
earlier, the commit operation enables you to specify whether it
is carried out asynchronously, semi-synchronously, or synchronously
and whether Autocommit mode is used. The state of any open row
sets depends on the DBPROP_COMMITPRESERVE property (a
Rowset object group property). If DBPROP_COMMITPRESERVE
is true, the row set remains valid and is automatically
synchronized when the transaction is committed or aborted; otherwise,
the row set becomes invalid. This property is set on the basis
of row set by row set. The Commit method is provided
through the ITransaction interface, so you must access
this interface to access the Commit method. The Commit
method will commit the transaction at the current level. Listing
20.4 demonstrates how to commit the transaction started in Listing
20.3. Note that you should check the return value of QueryInterface
in your production code.
Listing 20.4 How to Commit the Current Transaction
1: // Commit The Transaction 2: pCreateCommand->QueryInterface(IID_ITransaction, (void **) &pTrans); 3: pTrans->Commit(FALSE,XATTC_SYNC,0);
Aborting a transaction is just as easy. Listing 20.5 demonstrates how to use the Abort method to abort a transaction at the current level. Again, note that you should check the return value of QueryInterface in your production code.
Listing 20.5 How to Abort the Current Transaction
1: // Abort The Transaction 2: pCreateCommand->QueryInterface(IID_ITransactionLocal, (void **) &pTrans); 3: pTrans->Abort(NULL, FALSE, TRUE);
If the data provider supports it, transactions can be nested. A nested transaction is created by starting a transaction while another transaction is already open. The inner transaction must be released before outer transactions can be committed or aborted.
OLE DB supports four levels of transaction isolation, which ensures coherent access to a data source. The transaction levels are Read Uncommitted, Read Committed, Repeatable Read, and Serializable.
With Read Committed isolation, any row sets that are created will view only rows that have been changed after those changes have been committed. Operations in this type of isolation level will see any rows that have been added or deleted. With Repeatable Read isolation, any changes to rows already read will not be seen, and any operation that deletes a row will not be seen. Any new rows that have been added will be visible. With Read Uncommitted, no attempt is made to isolate any types of changes. Rows that are retrieved will reflect the current database state. Finally, with Serializable isolation, the rows retrieved are guaranteed to be in the consistent state, reflecting only the changes of the current transaction.
Provider-specific, user-defined locking mechanisms implement these
isolation levels. Table 20.7 defines the constants related to
each isolation level. The isolation level is determined when the
StartTransaction method starts a transaction.
ISOLATIONLEVEL_UNSPECIFIED | Used only with the JoinTransaction method |
ISOLATIONLEVEL_CHAOS | Preserves changes made by higher-level transactions |
ISOLATIONLEVEL_READUNCOMMITTED | Read Uncommitted isolation |
ISOLATIONLEVEL_BROWSE | Read Uncommitted isolation |
ISOLATIONLEVEL_READCOMMITTED | Read Committed isolation |
ISOLATIONLEVEL_CURSORSTABILITY | Read Committed isolation |
ISOLATIONLEVEL_REPEATABLEREAD | Repeatable Read isolation |
ISOLATIONLEVEL_SERIALIZABLE | Serializable isolation |
ISOLATIONLEVEL_ISOLATED | Serializable isolation |
The final OLE DB object today is the Index object. The Index object can directly access a data source index through a row set mechanism. Index objects access data source tables in a sorted manner and search for records, based on a key value. The TIndex CoType is defined as follows:
TIndex { interface IAccessor; // Required Interface interface IColumnsInfo; // Required Interface interface IConvertType; // Required Interface interface IRowset; // Required Interface interface IRowsetIndex; // Required Interface interface IRowsetInfo; // Required Interface interface IRowsetChange; interface ISupportErrorInfo; };
You have already seen all these interfaces-except for the IRowsetIndex interface-in the context of the Rowset object. The next section describes the IRowsetIndex interface and explains how to implement the Index object.
The IRowsetIndex interface is required by the Index object. It retrieves index information, searches for specific key values, and limits the set of visible rows to a range of key values. The IRowsetIndex interface defines the standard IUnknown interface methods QueryInterface, AddRef, and Release. The interface also provides three more methods: GetIndexInfo, Seek, and SetRange. These methods are defined as follows:
HRESULT GetIndexInfo(ULONG *plNumKeyCols, DBINDEXCOLUMNDESC **pprdIdxColDesc, ULONG *plNumIdxProps, DBPROPSET **prgIdxProps); HRESULT Seek(HACCESSOR hAccessor, ULONG lNumKeys, void *pSeekData, DBSEEK dwSeekOpt); HRESULT SetRange(HACCESSOR hAccessor, ULONG lNumStartKeyCols, void *pStartKeyData, ULONG lNumEndKeyCols, void *pEndKeyData, DBRANGE dwRangeOpt);
The GetIndexInfo method retrieves information about the index. The plNumKeyCols parameter returns the number of key columns in this index. The prdIdxColDesc parameter returns an array that describes each column. The plNumIdxProps parameter returns the number of elements in the prgIdxProps array. The prgIdxProps parameter returns an array that holds a collection of index properties.
TIP |
Partial key searches are possible with the Seek method. You must supply the complete key set binding and then include only the partial key value for the key value. |
The Seek method searches for a specific record in the
index row set. The hAccessor parameter holds an Accessor
to a set of bindings that describe the key structure. The lNumKeys
parameter specifies the number of keys in the search criteria.
The pSeekData parameter specifies the key set data for
which you are searching. The dwSeekOpt parameter specifies
the seek options. Seek options are outlined in Table 20.8.
DBSEEK_FIRSTEQ | Searches for the first value that matches the key specified. |
DBSEEK_LASTEQ | Searches for the last value that matches the key specified. |
DBSEEK_GE | Searches for the first value that is greater than or equal to the key specified. |
DBSEEK_GT | Searches for the first value that is greater than the key specified. |
DBSEEK_LE | Searches for the first value that is less than or equal to the key specified. |
DBSEEK_LT | Searches for the first value that is less than the key specified. |
The SetRange method restricts the rows visible in the
index row set to a range of key values. The hAccessor
parameter holds an Accessor to a set of bindings that describe
the key structure. The lNumStartKeyCols defines the number
of key columns in the start range key. The pStartKeyData
parameter specifies the start key data. The lNumEndKeyCols
defines the number of key columns in the end range key. The pEndKeyData
parameter specifies the end key data. The dwRangeOpt
parameter specifies how the start and end keys will be used to
limit the rows that will be visible. Table 20.9 defines the range
options. These options can be combined with a logical OR
operation.
DBRANGE_INCLUSIVESTART | Includes all keys greater than or equal to the start key. |
DBRANGE_EXCLUSIVESTART | Includes all keys greater than the start key. |
DBRANGE_INCLUSIVEEND | Includes all keys less than or equal to the end key. |
DBRANGE_EXCLUSIVEEND | Includes all keys less than the end key. |
DBRANGE_EXCLUDENULLS | Excludes NULL values from the range. |
DBRANGE_PREFIX | Uses the start key as a prefix, which enables faster searches on some data sources. |
DBRANGE_MATCH | Includes only keys that are equal to the start key. The end key must be NULL if this flag is set. |
Here's how to open and use an Index object:
NOTE |
Rather than rely on your OLE DB provider's support for the IRowsetIndex interface, you might need to use the appropriate SQL commands to retrieve specific rows or to retrieve rows in a specific order. |
Day 20 focuses on three main topics: OLE DB properties and groups, the Transaction object, and the Index object. Today you learned how to retrieve and set property values and how to use the different types associated with properties. You reviewed the set of properties that OLE DB objects support and how to use these properties to determine whether a data source supports use of the SQL command language. You learned how to use the Transaction object to encapsulate your data source operations and to commit and abort transactions. Other transaction-related topics discussed today are nesting transaction, transaction isolation levels, and how to control locking. Today's final topic is the Index object, its associated interfaces, and how to use the Index object to search for specific rows in a row set that contain specific key values. Tomorrow's theme is how to integrate error handling into your OLE DB applications.
This section answers some common questions related to today's
topics.
How can you use transactions to improve application performance? | |
When a transaction is opened, all operations that are performed are buffered until they are committed or aborted. In a client/server environment, using transactions can cut down on the network traffic. Only transactions that actually commit are transmitted to the server data source. This performance improvement doesn't come without a cost, however. In this case, the cost can be higher memory requirements (physical or disk space) on the client side. In a multiuser environment, though, this tradeoff can be worthwhile because it can yield significant performance improvements under the right conditions. | |
How do isolation levels relate to specific locking schemes? | |
OLE DB doesn't specify the locking mechanisms used by a provider. The OLE DB specification leaves it to the data provider to implement its own appropriate locking methods that support the defined isolation levels. When using OLE DB, you should focus on isolation levels rather than on specific locking mechanisms, and you must use transactions to invoke these locking methodologies. | |
How can you determine whether a data provider supports its own set of properties? | |
You can use the GetPropertyInfo method of the IDBProperties interface to return information about all properties supported by the data provider. This method returns a DBPROPINFOSET structure that contains information about each property supported by a data provider. You must navigate through this structure to determine the provider-specific properties it supports. |
The Workshop quiz questions test your understanding of today's material. (The answers appear in Appendix F, "Answers.") The exercises encourage you to apply the information you learned today to real-life situations.
© Copyright, Sams Publishing. All rights reserved.