Freigeben über


CDaoRecordset Class

 

The latest version of this topic can be found at CDaoRecordset Class.

Represents a set of records selected from a data source.

Syntax

class CDaoRecordset : public CObject  

Members

Public Constructors

Name Description
CDaoRecordset::CDaoRecordset Constructs a CDaoRecordset object.

Public Methods

Name Description
CDaoRecordset::AddNew Prepares for adding a new record. Call Update to complete the addition.
CDaoRecordset::CanAppend Returns nonzero if new records can be added to the recordset via the AddNew member function.
CDaoRecordset::CanBookmark Returns nonzero if the recordset supports bookmarks.
CDaoRecordset::CancelUpdate Cancels any pending updates due to an Edit or AddNew operation.
CDaoRecordset::CanRestart Returns nonzero if Requery can be called to run the recordset's query again.
CDaoRecordset::CanScroll Returns nonzero if you can scroll through the records.
CDaoRecordset::CanTransact Returns nonzero if the data source supports transactions.
CDaoRecordset::CanUpdate Returns nonzero if the recordset can be updated (you can add, update, or delete records).
CDaoRecordset::Close Closes the recordset.
CDaoRecordset::Delete Deletes the current record from the recordset. You must explicitly scroll to another record after the deletion.
CDaoRecordset::DoFieldExchange Called to exchange data (in both directions) between the field data members of the recordset and the corresponding record on the data source. Implements DAO record field exchange (DFX).
CDaoRecordset::Edit Prepares for changes to the current record. Call Update to complete the edit.
CDaoRecordset::FillCache Fills all or a part of a local cache for a recordset object that contains data from an ODBC data source.
CDaoRecordset::Find Locates the first, next, previous, or last location of a particular string in a dynaset-type recordset that satisfies the specified criteria and makes that record the current record.
CDaoRecordset::FindFirst Locates the first record in a dynaset-type or snapshot-type recordset that satisfies the specified criteria and makes that record the current record.
CDaoRecordset::FindLast Locates the last record in a dynaset-type or snapshot-type recordset that satisfies the specified criteria and makes that record the current record.
CDaoRecordset::FindNext Locates the next record in a dynaset-type or snapshot-type recordset that satisfies the specified criteria and makes that record the current record.
CDaoRecordset::FindPrev Locates the previous record in a dynaset-type or snapshot-type recordset that satisfies the specified criteria and makes that record the current record.
CDaoRecordset::GetAbsolutePosition Returns the record number of a recordset object's current record.
CDaoRecordset::GetBookmark Returns a value that represents the bookmark on a record.
CDaoRecordset::GetCacheSize Returns a value that specifies the number of records in a dynaset-type recordset containing data to be locally cached from an ODBC data source.
CDaoRecordset::GetCacheStart Returns a value that specifies the bookmark of the first record in the recordset to be cached.
CDaoRecordset::GetCurrentIndex Returns a CString containing the name of the index most recently used on an indexed, table-type CDaoRecordset.
CDaoRecordset::GetDateCreated Returns the date and time the base table underlying a CDaoRecordset object was created
CDaoRecordset::GetDateLastUpdated Returns the date and time of the most recent change made to the design of a base table underlying a CDaoRecordset object.
CDaoRecordset::GetDefaultDBName Returns the name of the default data source.
CDaoRecordset::GetDefaultSQL Called to get the default SQL string to execute.
CDaoRecordset::GetEditMode Returns a value that indicates the state of editing for the current record.
CDaoRecordset::GetFieldCount Returns a value that represents the number of fields in a recordset.
CDaoRecordset::GetFieldInfo Returns specific kinds of information about the fields in the recordset.
CDaoRecordset::GetFieldValue Returns the value of a field in a recordset.
CDaoRecordset::GetIndexCount Retrieves the number of indexes in a table underlying a recordset.
CDaoRecordset::GetIndexInfo Returns various kinds of information about an index.
CDaoRecordset::GetLastModifiedBookmark Used to determine the most recently added or updated record.
CDaoRecordset::GetLockingMode Returns a value that indicates the type of locking that is in effect during editing.
CDaoRecordset::GetName Returns a CString containing the name of the recordset.
CDaoRecordset::GetParamValue Retrieves the current value of the specified parameter stored in the underlying DAOParameter object.
CDaoRecordset::GetPercentPosition Returns the position of the current record as a percentage of the total number of records.
CDaoRecordset::GetRecordCount Returns the number of records accessed in a recordset object.
CDaoRecordset::GetSQL Gets the SQL string used to select records for the recordset.
CDaoRecordset::GetType Called to determine the type of a recordset: table-type, dynaset-type, or snapshot-type.
CDaoRecordset::GetValidationRule Returns a CString containing the value that validates data as it is entered into a field.
CDaoRecordset::GetValidationText Retrieves the text that is displayed when a validation rule is not satisfied.
CDaoRecordset::IsBOF Returns nonzero if the recordset has been positioned before the first record. There is no current record.
CDaoRecordset::IsDeleted Returns nonzero if the recordset is positioned on a deleted record.
CDaoRecordset::IsEOF Returns nonzero if the recordset has been positioned after the last record. There is no current record.
CDaoRecordset::IsFieldDirty Returns nonzero if the specified field in the current record has been changed.
CDaoRecordset::IsFieldNull Returns nonzero if the specified field in the current record is Null (having no value).
CDaoRecordset::IsFieldNullable Returns nonzero if the specified field in the current record can be set to Null (having no value).
CDaoRecordset::IsOpen Returns nonzero if Open has been called previously.
CDaoRecordset::Move Positions the recordset to a specified number of records from the current record in either direction.
CDaoRecordset::MoveFirst Positions the current record on the first record in the recordset.
CDaoRecordset::MoveLast Positions the current record on the last record in the recordset.
CDaoRecordset::MoveNext Positions the current record on the next record in the recordset .
CDaoRecordset::MovePrev Positions the current record on the previous record in the recordset.
CDaoRecordset::Open Creates a new recordset from a table, dynaset, or snapshot.
CDaoRecordset::Requery Runs the recordset's query again to refresh the selected records.
CDaoRecordset::Seek Locates the record in an indexed table-type recordset object that satisfies the specified criteria for the current index and makes that record the current record.
CDaoRecordset::SetAbsolutePosition Sets the record number of a recordset object's current record.
CDaoRecordset::SetBookmark Positions the recordset on a record containing the specified bookmark.
CDaoRecordset::SetCacheSize Sets a value that specifies the number of records in a dynaset-type recordset containing data to be locally cached from an ODBC data source.
CDaoRecordset::SetCacheStart Sets a value that specifies the bookmark of the first record in the recordset to be cached.
CDaoRecordset::SetCurrentIndex Called to set an index on a table-type recordset.
CDaoRecordset::SetFieldDirty Marks the specified field in the current record as changed.
CDaoRecordset::SetFieldNull Sets the value of the specified field in the current record to Null (having no value).
CDaoRecordset::SetFieldValue Sets the value of a field in a recordset.
CDaoRecordset::SetFieldValueNull Sets the value of a field in a recordset to Null. (having no value).
CDaoRecordset::SetLockingMode Sets a value that indicates the type of locking to put into effect during editing.
CDaoRecordset::SetParamValue Sets the current value of the specified parameter stored in the underlying DAOParameter object
CDaoRecordset::SetParamValueNull Sets the current value of the specified parameter to Null (having no value).
CDaoRecordset::SetPercentPosition Sets the position of the current record to a location corresponding to a percentage of the total number of records in a recordset.
CDaoRecordset::Update Completes an AddNew or Edit operation by saving the new or edited data on the data source.

Public Data Members

Name Description
CDaoRecordset::m_bCheckCacheForDirtyFields Contains a flag indicating whether fields are automatically marked as changed.
CDaoRecordset::m_nFields Contains the number of field data members in the recordset class and the number of columns selected by the recordset from the data source.
CDaoRecordset::m_nParams Contains the number of parameter data members in the recordset class — the number of parameters passed with the recordset's query
CDaoRecordset::m_pDAORecordset A pointer to the DAO interface underlying the recordset object.
CDaoRecordset::m_pDatabase Source database for this result set. Contains a pointer to a CDaoDatabase object.
CDaoRecordset::m_strFilter Contains a string used to construct a SQL WHERE statement.
CDaoRecordset::m_strSort Contains a string used to construct a SQL ORDER BY statement.

Remarks

Known as "recordsets," CDaoRecordset objects are available in the following three forms:

  • Table-type recordsets represent a base table that you can use to examine, add, change, or delete records from a single database table.

  • Dynaset-type recordsets are the result of a query that can have updateable records. These recordsets are a set of records that you can use to examine, add, change, or delete records from an underlying database table or tables. Dynaset-type recordsets can contain fields from one or more tables in a database.

  • Snapshot-type recordsets are a static copy of a set of records that you can use to find data or generate reports. These recordsets can contain fields from one or more tables in a database but cannot be updated.

Each form of recordset represents a set of records fixed at the time the recordset is opened. When you scroll to a record in a table-type recordset or a dynaset-type recordset, it reflects changes made to the record after the recordset is opened, either by other users or by other recordsets in your application. (A snapshot-type recordset cannot be updated.) You can use CDaoRecordset directly or derive an application-specific recordset class from CDaoRecordset. You can then:

  • Scroll through the records.

  • Set an index and quickly look for records using Seek (table-type recordsets only).

  • Find records based on a string comparison: "<", "<=", "=", ">=", or ">" (dynaset-type and snapshot-type recordsets).

  • Update the records and specify a locking mode (except snapshot-type recordsets).

  • Filter the recordset to constrain which records it selects from those available on the data source.

  • Sort the recordset.

  • Parameterize the recordset to customize its selection with information not known until run time.

Class CDaoRecordset supplies an interface similar to that of class CRecordset. The main difference is that class CDaoRecordset accesses data through a Data Access Object (DAO) based on OLE. Class CRecordset accesses the DBMS through Open Database Connectivity (ODBC) and an ODBC driver for that DBMS.

Note

The DAO database classes are distinct from the MFC database classes based on Open Database Connectivity (ODBC). All DAO database class names have the "CDao" prefix. You can still access ODBC data sources with the DAO classes; the DAO classes generally offer superior capabilities because they are specific to the Microsoft Jet database engine.

You can either use CDaoRecordset directly or derive a class from CDaoRecordset. To use a recordset class in either case, open a database and construct a recordset object, passing the constructor a pointer to your CDaoDatabase object. You can also construct a CDaoRecordset object and let MFC create a temporary CDaoDatabase object for you. Then call the recordset's Open member function, specifying whether the object is a table-type recordset, a dynaset-type recordset, or a snapshot-type recordset. Calling Open selects data from the database and retrieves the first record.

Use the object's member functions and data members to scroll through the records and operate on them. The operations available depend on whether the object is a table-type recordset, a dynaset-type recordset, or a snapshot-type recordset, and whether it is updateable or read-only — this depends on the capability of the database or Open Database Connectivity (ODBC) data source. To refresh records that may have been changed or added since the Open call, call the object's Requery member function. Call the object's Close member function and destroy the object when you finish with it.

CDaoRecordset uses DAO record field exchange (DFX) to support reading and updating of record fields through type-safe C++ members of your CDaoRecordset or CDaoRecordset-derived class. You can also implement dynamic binding of columns in a database without using the DFX mechanism using GetFieldValue and SetFieldValue.

For related information, see the topic "Recordset Object" in DAO Help.

Inheritance Hierarchy

CObject

CDaoRecordset

Requirements

Header: afxdao.h

CDaoRecordset::AddNew

Call this member function to add a new record to a table-type or dynaset-type recordset.

virtual void AddNew();

Remarks

The record's fields are initially Null. (In database terminology, Null means "having no value" and is not the same as NULL in C++.) To complete the operation, you must call the Update member function. Update saves your changes to the data source.

Warning

If you edit a record and then scroll to another record without calling Update, your changes are lost without warning.

If you add a record to a dynaset-type recordset by calling AddNew, the record is visible in the recordset and included in the underlying table where it becomes visible to any new CDaoRecordset objects.

The position of the new record depends on the type of recordset:

  • In a dynaset-type recordset, where the new record is inserted is not guaranteed. This behavior changed with Microsoft Jet 3.0 for reasons of performance and concurrency. If your goal is to make the newly added record the current record, get the bookmark of the last modified record and move to that bookmark:
   rs.SetBookmark(rs.GetLastModifiedBookmark());
  • In a table-type recordset for which an index has been specified, records are returned in their proper place in the sort order. If no index has been specified, new records are returned at the end of the recordset.

The record that was current before you used AddNew remains current. If you want to make the new record current and the recordset supports bookmarks, call SetBookmark to the bookmark identified by the LastModified property setting of the underlying DAO recordset object. Doing so is useful for determining the value for counter (auto-increment) fields in an added record. For more information, see GetLastModifiedBookmark.

If the database supports transactions, you can make your AddNew call part of a transaction. For more information about transactions, see class CDaoWorkspace. Note that you should call CDaoWorkspace::BeginTrans before calling AddNew.

It is illegal to call AddNew for a recordset whose Open member function has not been called. A CDaoException is thrown if you call AddNew for a recordset that cannot be appended. You can determine whether the recordset is updateable by calling CanAppend.

The framework marks changed field data members to ensure they will be written to the record on the data source by the DAO record field exchange (DFX) mechanism. Changing the value of a field generally sets the field dirty automatically, so you will seldom need to call SetFieldDirty yourself, but you might sometimes want to ensure that columns will be explicitly updated or inserted regardless of what value is in the field data member. The DFX mechanism also employs the use of PSEUDO NULL. For more information, see CDaoFieldExchange::m_nOperation.

If the double-buffering mechanism is not being used, then changing the value of the field does not automatically set the field as dirty. In this case, it will be necessary to explicitly set the field dirty. The flag contained in m_bCheckCacheForDirtyFields controls this automatic field checking.

Note

If records are double-buffered (that is, automatic field checking is enabled), calling CancelUpdate will restore the member variables to the values they had before AddNew or Edit was called.

For related information, see the topics "AddNew Method", "CancelUpdate Method", "LastModified Property", and "EditMode Property" in DAO Help.

CDaoRecordset::CanAppend

Call this member function to determine whether the previously opened recordset allows you to add new records by calling the AddNew member function.

BOOL CanAppend() const;  

Return Value

Nonzero if the recordset allows adding new records; otherwise 0. CanAppend will return 0 if you opened the recordset as read-only.

Remarks

For related information, see the topic "Append Method" in DAO Help.

CDaoRecordset::CanBookmark

Call this member function to determine whether the previously opened recordset allows you to individually mark records using bookmarks.

BOOL CanBookmark();

Return Value

Nonzero if the recordset supports bookmarks, otherwise 0.

Remarks

If you are using recordsets based entirely on Microsoft Jet database engine tables, bookmarks can be used except on snapshot-type recordsets flagged as forward-only scrolling recordsets. Other database products (external ODBC data sources) may not support bookmarks.

For related information, see the topic "Bookmarkable Property" in DAO Help.

CDaoRecordset::CancelUpdate

The CancelUpdate member function cancels any pending updates due to an Edit or AddNew operation.

virtual void CancelUpdate();

Remarks

For example, if an application calls the Edit or AddNew member function and has not called Update, CancelUpdate cancels any changes made after Edit or AddNew was called.

Note

If records are double-buffered (that is, automatic field checking is enabled), calling CancelUpdate will restore the member variables to the values they had before AddNew or Edit was called.

If there is no Edit or AddNew operation pending, CancelUpdate causes MFC to throw an exception. Call the GetEditMode member function to determine if there is a pending operation that can be canceled.

For related information, see the topic "CancelUpdate Method" in DAO Help.

CDaoRecordset::CanRestart

Call this member function to determine whether the recordset allows restarting its query (to refresh its records) by calling the Requery member function.

BOOL CanRestart();

Return Value

Nonzero if Requery can be called to run the recordset's query again, otherwise 0.

Remarks

Table-type recordsets do not support Requery.

If Requery is not supported, call Close then Open to refresh the data. You can call Requery to update a recordset object's underlying parameter query after the parameter values have been changed.

For related information, see the topic "Restartable Property" in DAO Help.

CDaoRecordset::CanScroll

Call this member function to determine whether the recordset allows scrolling.

BOOL CanScroll() const;  

Return Value

Nonzero if you can scroll through the records, otherwise 0.

Remarks

If you call Open with dbForwardOnly, the recordset can only scroll forward.

For related information, see the topic "Positioning the Current Record Pointer with DAO" in DAO Help.

CDaoRecordset::CanTransact

Call this member function to determine whether the recordset allows transactions.

BOOL CanTransact();

Return Value

Nonzero if the underlying data source supports transactions, otherwise 0.

Remarks

For related information, see the topic "Transactions Property" in DAO Help.

CDaoRecordset::CanUpdate

Call this member function to determine whether the recordset can be updated.

BOOL CanUpdate() const;  

Return Value

Nonzero if the recordset can be updated (add, update, and delete records), otherwise 0.

Remarks

A recordset might be read-only if the underlying data source is read-only or if you specified dbReadOnly for nOptions when you called Open for the recordset.

For related information, see the topics "AddNew Method", "Edit Method", "Delete Method", "Update Method", and "Updatable Property" in DAO Help.

CDaoRecordset::CDaoRecordset

Constructs a CDaoRecordset object.

CDaoRecordset(CDaoDatabase* pDatabase = NULL);

Parameters

pDatabase
Contains a pointer to a CDaoDatabase object or the value NULL. If not NULL and the CDaoDatabase object's Open member function has not been called to connect it to the data source, the recordset attempts to open it for you during its own Open call. If you pass NULL, a CDaoDatabase object is constructed and connected for you using the data source information you specified if you derived your recordset class from CDaoRecordset.

Remarks

You can either use CDaoRecordset directly or derive an application-specific class from CDaoRecordset. You can use ClassWizard to derive your recordset classes.

Note

If you derive a CDaoRecordset class, your derived class must supply its own constructor. In the constructor of your derived class, call the constructor CDaoRecordset::CDaoRecordset, passing the appropriate parameters along to it.

Pass NULL to your recordset constructor to have a CDaoDatabase object constructed and connected for you automatically. This is a useful shortcut that does not require you to construct and connect a CDaoDatabase object prior to constructing your recordset. If the CDaoDatabase object is not open, a CDaoWorkspace object will also be created for you that uses the default workspace. For more information, see CDaoDatabase::CDaoDatabase.

CDaoRecordset::Close

Closing a CDaoRecordset object removes it from the collection of open recordsets in the associated database.

virtual void Close();

Remarks

Because Close does not destroy the CDaoRecordset object, you can reuse the object by calling Open on the same data source or a different data source.

All pending AddNew or Edit statements are canceled, and all pending transactions are rolled back. If you want to preserve pending additions or edits, call Update before you call Close for each recordset.

You can call Open again after calling Close. This lets you reuse the recordset object. A better alternative is to call Requery, if possible.

For related information, see the topic "Close Method" in DAO Help.

CDaoRecordset::Delete

Call this member function to delete the current record in an open dynaset-type or table-type recordset object.

virtual void Delete();

Remarks

After a successful deletion, the recordset's field data members are set to a Null value, and you must explicitly call one of the recordset navigation member functions ( Move, Seek, SetBookmark, and so on) in order to move off the deleted record. When you delete records from a recordset, there must be a current record in the recordset before you call Delete; otherwise, MFC throws an exception.

Delete removes the current record and makes it inaccessible. Although you cannot edit or use the deleted record, it remains current. Once you move to another record, however, you cannot make the deleted record current again.

Warning

The recordset must be updatable and there must be a valid record current in the recordset when you call Delete. For example, if you delete a record but do not scroll to a new record before you call Delete again, Delete throws a CDaoException.

You can undelete a record if you use transactions and you call the CDaoWorkspace::Rollback member function. If the base table is the primary table in a cascade delete relationship, deleting the current record may also delete one or more records in a foreign table. For more information, see the definition "cascade delete" in DAO Help.

Unlike AddNew and Edit, a call to Delete is not followed by a call to Update.

For related information, see the topics "AddNew Method", "Edit Method", "Delete Method", "Update Method", and "Updatable Property" in DAO Help.

CDaoRecordset::DoFieldExchange

The framework calls this member function to automatically exchange data between the field data members of your recordset object and the corresponding columns of the current record on the data source.

virtual void DoFieldExchange(CDaoFieldExchange* pFX);

Parameters

pFX
Contains a pointer to a CDaoFieldExchange object. The framework will already have set up this object to specify a context for the field exchange operation.

Remarks

It also binds your parameter data members, if any, to parameter placeholders in the SQL statement string for the recordset's selection. The exchange of field data, called DAO record field exchange (DFX), works in both directions: from the recordset object's field data members to the fields of the record on the data source, and from the record on the data source to the recordset object. If you are binding columns dynamically, you are not required to implement DoFieldExchange.

The only action you must normally take to implement DoFieldExchange for your derived recordset class is to create the class with ClassWizard and specify the names and data types of the field data members. You might also add code to what ClassWizard writes to specify parameter data members. If all fields are to be bound dynamically, this function will be inactive unless you specify parameter data members.

When you declare your derived recordset class with ClassWizard, the wizard writes an override of DoFieldExchange for you, which resembles the following example:

void CCustSet::DoFieldExchange(CDaoFieldExchange* pFX)
{
   pFX->SetFieldType(CDaoFieldExchange::param);
   DFX_Text(pFX, _T("Param"), m_strParam);
   pFX->SetFieldType(CDaoFieldExchange::outputColumn);
   DFX_Short(pFX, _T("EmployeeID"), m_EmployeeID);
   DFX_Text(pFX, _T("LastName"), m_LastName);
   DFX_Short(pFX, _T("Age"), m_Age);
   DFX_DateTime(pFX, _T("hire_date"), m_hire_date);
   DFX_DateTime(pFX, _T("termination_date"), m_termination_date);

   CDaoRecordset::DoFieldExchange(pFX);
}

CDaoRecordset::Edit

Call this member function to allow changes to the current record.

virtual void Edit();

Remarks

Once you call the Edit member function, changes made to the current record's fields are copied to the copy buffer. After you make the desired changes to the record, call Update to save your changes. Edit saves the values of the recordset's data members. If you call Edit, make changes, then call Edit again, the record's values are restored to what they were before the first Edit call.

Warning

If you edit a record and then perform any operation that moves to another record without first calling Update, your changes are lost without warning. In addition, if you close the recordset or the parent database, your edited record is discarded without warning.

In some cases, you may want to update a column by making it Null (containing no data). To do so, call SetFieldNull with a parameter of TRUE to mark the field Null; this also causes the column to be updated. If you want a field to be written to the data source even though its value has not changed, call SetFieldDirty with a parameter of TRUE. This works even if the field had the value Null.

The framework marks changed field data members to ensure they will be written to the record on the data source by the DAO record field exchange (DFX) mechanism. Changing the value of a field generally sets the field dirty automatically, so you will seldom need to call SetFieldDirty yourself, but you might sometimes want to ensure that columns will be explicitly updated or inserted regardless of what value is in the field data member. The DFX mechanism also employs the use of PSEUDO NULL. For more information, see CDaoFieldExchange::m_nOperation.

If the double-buffering mechanism is not being used, then changing the value of the field does not automatically set the field as dirty. In this case, it will be necessary to explicitly set the field dirty. The flag contained in m_bCheckCacheForDirtyFields controls this automatic field checking.

When the recordset object is pessimistically locked in a multiuser environment, the record remains locked from the time Edit is used until the updating is complete. If the recordset is optimistically locked, the record is locked and compared with the pre-edited record just before it is updated in the database. If the record has changed since you called Edit, the Update operation fails and MFC throws an exception. You can change the locking mode with SetLockingMode.

Note

Optimistic locking is always used on external database formats, such as ODBC and installable ISAM.

The current record remains current after you call Edit. To call Edit, there must be a current record. If there is no current record or if the recordset does not refer to an open table-type or dynaset-type recordset object, an exception occurs. Calling Edit causes a CDaoException to be thrown under the following conditions:

  • There is no current record.

  • The database or recordset is read-only.

  • No fields in the record are updatable.

  • The database or recordset was opened for exclusive use by another user.

  • Another user has locked the page containing your record.

If the data source supports transactions, you can make the Edit call part of a transaction. Note that you should call CDaoWorkspace::BeginTrans before calling Edit and after the recordset has been opened. Also note that calling CDaoWorkspace::CommitTrans is not a substitute for calling Update to complete the Edit operation. For more information about transactions, see class CDaoWorkspace.

For related information, see the topics "AddNew Method", "Edit Method", "Delete Method", "Update Method", and "Updatable Property" in DAO Help.

CDaoRecordset::FillCache

Call this member function to cache a specified number of records from the recordset.

void FillCache(
    long* pSize = NULL,  
    COleVariant* pBookmark = NULL);

Parameters

pSize
Specifies the number of rows to fill in the cache. If you omit this parameter, the value is determined by the CacheSize property setting of the underlying DAO object.

pBookmark
A COleVariant specifying a bookmark. The cache is filled starting from the record indicated by this bookmark. If you omit this parameter, the cache is filled starting from the record indicated by the CacheStart property of the underlying DAO object.

Remarks

Caching improves the performance of an application that retrieves, or fetches, data from a remote server. A cache is space in local memory that holds the data most recently fetched from the server on the assumption that the data will probably be requested again while the application is running. When data is requested, the Microsoft Jet database engine checks the cache for the data first rather than fetching it from the server, which takes more time. Using data caching on non-ODBC data sources has no effect as the data is not saved in the cache.

Rather than waiting for the cache to be filled with records as they are fetched, you can explicitly fill the cache at any time by calling the FillCache member function. This is a faster way to fill the cache because FillCache fetches several records at once instead of one at a time. For example, while each screenful of records is being displayed, you can have your application call FillCache to fetch the next screenful of records.

Any ODBC database accessed with recordset objects can have a local cache. To create the cache, open a recordset object from the remote data source, and then call the SetCacheSize and SetCacheStart member functions of the recordset. If lSize and lBookmark create a range that is partly or wholly outside the range specified by SetCacheSize and SetCacheStart, the portion of the recordset outside this range is ignored and is not loaded into the cache. If FillCache requests more records than remain in the remote data source, only the remaining records are fetched, and no exception is thrown.

Records fetched from the cache do not reflect changes made concurrently to the source data by other users.

FillCache fetches only records not already cached. To force an update of all the cached data, call the SetCacheSize member function with an lSize parameter equal to 0, call SetCacheSize again with the lSize parameter equal to the size of the cache you originally requested, and then call FillCache.

For related information, see the topic "FillCache Method" in DAO Help.

CDaoRecordset::Find

Call this member function to locate a particular string in a dynaset- or snapshot-type recordset using a comparison operator.

virtual BOOL Find(
    long lFindType,  
    LPCTSTR lpszFilter);

Parameters

lFindType
A value indicating the type of Find operation desired. The possible values are:

  • AFX_DAO_NEXT Find the next location of a matching string.

  • AFX_DAO_PREV Find the previous location of a matching string.

  • AFX_DAO_FIRST Find the first location of a matching string.

  • AFX_DAO_LAST Find the last location of a matching string.

lpszFilter
A string expression (like the WHERE clause in a SQL statement without the word WHERE) used to locate the record. For example:

   rs.Find(AFX_DAO_FIRST, _T("EmployeeID = 7"));
   rs.Find(AFX_DAO_NEXT, _T("LastName = 'Jones'"));

Return Value

Nonzero if matching records are found, otherwise 0.

Remarks

You can find the first, next, previous, or last instance of the string. Find is a virtual function, so you can override it and add your own implementation. The FindFirst, FindLast, FindNext, and FindPrev member functions call the Find member function, so you can use Find to control the behavior of all Find operations.

To locate a record in a table-type recordset, call the Seek member function.

Tip

The smaller the set of records you have, the more effective Find will be. In general, and especially with ODBC data, it is better to create a new query that retrieves just the records you want.

For related information, see the topic "FindFirst, FindLast, FindNext, FindPrevious Methods" in DAO Help.

CDaoRecordset::FindFirst

Call this member function to find the first record that matches a specified condition.

BOOL FindFirst(LPCTSTR lpszFilter);

Parameters

lpszFilter
A string expression (like the WHERE clause in a SQL statement without the word WHERE) used to locate the record.

Return Value

Nonzero if matching records are found, otherwise 0.

Remarks

The FindFirst member function begins its search from the beginning of the recordset and searches to the end of the recordset.

If you want to include all the records in your search (not just those that meet a specific condition) use one of the Move operations to move from record to record. To locate a record in a table-type recordset, call the Seek member function.

If a record matching the criteria is not located, the current record pointer is undetermined, and FindFirst returns zero. If the recordset contains more than one record that satisfies the criteria, FindFirst locates the first occurrence, FindNext locates the next occurrence, and so on.

Warning

If you edit the current record, be sure to save the changes by calling the Update member function before you move to another record. If you move to another record without updating, your changes are lost without warning.

The Find member functions search from the location and in the direction specified in the following table:

Find operations Begin Search direction
FindFirst Beginning of recordset End of recordset
FindLast End of recordset Beginning of recordset
FindNext Current record End of recordset
FindPrevious Current record Beginning of recordset

Note

When you call FindLast, the Microsoft Jet database engine fully populates your recordset before beginning the search, if this has not already been done. The first search may take longer than subsequent searches.

Using one of the Find operations is not the same as calling MoveFirst or MoveNext, however, which simply makes the first or next record current without specifying a condition. You can follow a Find operation with a Move operation.

Keep the following in mind when using the Find operations:

  • If Find returns nonzero, the current record is not defined. In this case, you must position the current record pointer back to a valid record.

  • You cannot use a Find operation with a forward-only scrolling snapshot-type recordset.

  • You should use the U.S. date format (month-day-year) when you search for fields containing dates, even if you are not using the U.S. version of the Microsoft Jet database engine; otherwise, matching records may not be found.

  • When working with ODBC databases and large dynasets, you may discover that using the Find operations is slow, especially when working with large recordsets. You can improve performance by using SQL queries with customized ORDERBY or WHERE clauses, parameter queries, or CDaoQuerydef objects that retrieve specific indexed records.

For related information, see the topic "FindFirst, FindLast, FindNext, FindPrevious Methods" in DAO Help.

CDaoRecordset::FindLast

Call this member function to find the last record that matches a specified condition.

BOOL FindLast(LPCTSTR lpszFilter);

Parameters

lpszFilter
A string expression (like the WHERE clause in a SQL statement without the word WHERE) used to locate the record.

Return Value

Nonzero if matching records are found, otherwise 0.

Remarks

The FindLast member function begins its search at the end of the recordset and searches backward towards the beginning of the recordset.

If you want to include all the records in your search (not just those that meet a specific condition) use one of the Move operations to move from record to record. To locate a record in a table-type recordset, call the Seek member function.

If a record matching the criteria is not located, the current record pointer is undetermined, and FindLast returns zero. If the recordset contains more than one record that satisfies the criteria, FindFirst locates the first occurrence, FindNext locates the next occurrence after the first occurrence, and so on.

Warning

If you edit the current record, be sure you save the changes by calling the Update member function before you move to another record. If you move to another record without updating, your changes are lost without warning.

Using one of the Find operations is not the same as calling MoveFirst or MoveNext, however, which simply makes the first or next record current without specifying a condition. You can follow a Find operation with a Move operation.

Keep the following in mind when using the Find operations:

  • If Find returns nonzero, the current record is not defined. In this case, you must position the current record pointer back to a valid record.

  • You cannot use a Find operation with a forward-only scrolling snapshot-type recordset.

  • You should use the U.S. date format (month-day-year) when you search for fields containing dates, even if you are not using the U.S. version of the Microsoft Jet database engine; otherwise, matching records may not be found.

  • When working with ODBC databases and large dynasets, you may discover that using the Find operations is slow, especially when working with large recordsets. You can improve performance by using SQL queries with customized ORDERBY or WHERE clauses, parameter queries, or CDaoQuerydef objects that retrieve specific indexed records.

For related information, see the topic "FindFirst, FindLast, FindNext, FindPrevious Methods" in DAO Help.

CDaoRecordset::FindNext

Call this member function to find the next record that matches a specified condition.

BOOL FindNext(LPCTSTR lpszFilter);

Parameters

lpszFilter
A string expression (like the WHERE clause in a SQL statement without the word WHERE) used to locate the record.

Return Value

Nonzero if matching records are found, otherwise 0.

Remarks

The FindNext member function begins its search at the current record and searches to the end of the recordset.

If you want to include all the records in your search (not just those that meet a specific condition) use one of the Move operations to move from record to record. To locate a record in a table-type recordset, call the Seek member function.

If a record matching the criteria is not located, the current record pointer is undetermined, and FindNext returns zero. If the recordset contains more than one record that satisfies the criteria, FindFirst locates the first occurrence, FindNext locates the next occurrence, and so on.

Warning

If you edit the current record, be sure you save the changes by calling the Update member function before you move to another record. If you move to another record without updating, your changes are lost without warning.

Using one of the Find operations is not the same as calling MoveFirst or MoveNext, however, which simply makes the first or next record current without specifying a condition. You can follow a Find operation with a Move operation.

Keep the following in mind when using the Find operations:

  • If Find returns nonzero, the current record is not defined. In this case, you must position the current record pointer back to a valid record.

  • You cannot use a Find operation with a forward-only scrolling snapshot-type recordset.

  • You should use the U.S. date format (month-day-year) when you search for fields containing dates, even if you are not using the U.S. version of the Microsoft Jet database engine; otherwise, matching records may not be found.

  • When working with ODBC databases and large dynasets, you may discover that using the Find operations is slow, especially when working with large recordsets. You can improve performance by using SQL queries with customized ORDERBY or WHERE clauses, parameter queries, or CDaoQuerydef objects that retrieve specific indexed records.

For related information, see the topic "FindFirst, FindLast, FindNext, FindPrevious Methods" in DAO Help.

CDaoRecordset::FindPrev

Call this member function to find the previous record that matches a specified condition.

BOOL FindPrev(LPCTSTR lpszFilter);

Parameters

lpszFilter
A string expression (like the WHERE clause in a SQL statement without the word WHERE) used to locate the record.

Return Value

Nonzero if matching records are found, otherwise 0.

Remarks

The FindPrev member function begins its search at the current record and searches backward towards the beginning of the recordset.

If you want to include all the records in your search (not just those that meet a specific condition) use one of the Move operations to move from record to record. To locate a record in a table-type recordset, call the Seek member function.

If a record matching the criteria is not located, the current record pointer is undetermined, and FindPrev returns zero. If the recordset contains more than one record that satisfies the criteria, FindFirst locates the first occurrence, FindNext locates the next occurrence, and so on.

Warning

If you edit the current record, be sure you save the changes by calling the Update member function before you move to another record. If you move to another record without updating, your changes are lost without warning.

Using one of the Find operations is not the same as calling MoveFirst or MoveNext, however, which simply makes the first or next record current without specifying a condition. You can follow a Find operation with a Move operation.

Keep the following in mind when using the Find operations:

  • If Find returns nonzero, the current record is not defined. In this case, you must position the current record pointer back to a valid record.

  • You cannot use a Find operation with a forward-only scrolling snapshot-type recordset.

  • You should use the U.S. date format (month-day-year) when you search for fields containing dates, even if you are not using the U.S. version of the Microsoft Jet database engine; otherwise, matching records may not be found.

  • When working with ODBC databases and large dynasets, you may discover that using the Find operations is slow, especially when working with large recordsets. You can improve performance by using SQL queries with customized ORDERBY or WHERE clauses, parameter queries, or CDaoQuerydef objects that retrieve specific indexed records.

For related information, see the topic "FindFirst, FindLast, FindNext, FindPrevious Methods" in DAO Help.

CDaoRecordset::GetAbsolutePosition

Returns the record number of a recordset object's current record.

long GetAbsolutePosition();

Return Value

An integer from 0 to the number of records in the recordset. Corresponds to the ordinal position of the current record in the recordset.

Remarks

The AbsolutePosition property value of the underlying DAO object is zero-based; a setting of 0 refers to the first record in the recordset. You can determine the number of populated records in the recordset by calling GetRecordCount. Calling GetRecordCount may take some time because it must access all records to determine the count.

If there is no current record, as when there are no records in the recordset, – 1 is returned. If the current record is deleted, the AbsolutePosition property value is not defined, and MFC throws an exception if it is referenced. For dynaset-type recordsets, new records are added to the end of the sequence.

Note

This property is not intended to be used as a surrogate record number. Bookmarks are still the recommended way of retaining and returning to a given position and are the only way to position the current record across all types of recordset objects. In particular, the position of a given record changes when record(s) preceding it are deleted. There is also no assurance that a given record will have the same absolute position if the recordset is re-created again because the order of individual records within a recordset is not guaranteed unless it is created with a SQL statement using an ORDERBY clause.

Note

This member function is valid only for dynaset-type and snapshot-type recordsets.

For related information, see the topic "AbsolutePosition Property" in DAO Help.

CDaoRecordset::GetBookmark

Call this member function to obtain the bookmark value in a particular record.

COleVariant GetBookmark();

Return Value

Returns a value representing the bookmark on the current record.

Remarks

When a recordset object is created or opened, each of its records already has a unique bookmark if it supports them. Call CanBookmark to determine whether a recordset supports bookmarks.

You can save the bookmark for the current record by assigning the value of the bookmark to a COleVariant object. To quickly return to that record at any time after moving to a different record, call SetBookmark with a parameter corresponding to the value of that COleVariant object.

Note

Calling Requery changes DAO bookmarks.

For related information, see the topic "Bookmark Property" in DAO Help.

CDaoRecordset::GetCacheSize

Call this member function to obtain the number of records cached.

long GetCacheSize();

Return Value

A value that specifies the number of records in a dynaset-type recordset containing data to be locally cached from an ODBC data source.

Remarks

Data caching improves the performance of an application that retrieves data from a remote server through dynaset-type recordset objects. A cache is a space in local memory that holds the data most recently retrieved from the server in the event that the data will be requested again while the application is running. When data is requested, the Microsoft Jet database engine checks the cache for the requested data first rather than retrieving it from the server, which takes more time. Data that does not come from an ODBC data source is not saved in the cache.

Any ODBC data source, such as an attached table, can have a local cache.

For related information, see the topic "CacheSize, CacheStart Properties" in DAO Help.

CDaoRecordset::GetCacheStart

Call this member function to obtain the bookmark value of the first record in the recordset to be cached.

COleVariant GetCacheStart();

Return Value

A COleVariant that specifies the bookmark of the first record in the recordset to be cached.

Remarks

The Microsoft Jet database engine requests records within the cache range from the cache, and it requests records outside the cache range from the server.

Note

Records retrieved from the cache do not reflect changes made concurrently to the source data by other users.

For related information, see the topic "CacheSize, CacheStart Properties" in DAO Help.

CDaoRecordset::GetCurrentIndex

Call this member function to determine the index currently in use in an indexed table-type CDaoRecordset object.

CString GetCurrentIndex();

Return Value

A CString containing the name of the index currently in use with a table-type recordset. Returns an empty string if no index has been set.

Remarks

This index is the basis for ordering records in a table-type recordset, and is used by the Seek member function to locate records.

A CDaoRecordset object can have more than one index but can use only one index at a time (although a CDaoTableDef object may have several indexes defined on it).

For related information, see the topic "Index Object" and the definition "current index" in DAO Help.

CDaoRecordset::GetDateCreated

Call this member function to retrieve the date and time a base table was created.

COleDateTime GetDateCreated();

Return Value

A COleDateTime object containing the date and time the base table was created.

Remarks

Date and time settings are derived from the computer on which the base table was created.

For related information, see the topic "DateCreated, LastUpdated Properties" in DAO Help.

CDaoRecordset::GetDateLastUpdated

Call this member function to retrieve the date and time the schema was last updated.

COleDateTime GetDateLastUpdated();

Return Value

A COleDateTime object containing the date and time the base table structure (schema) was last updated.

Remarks

Date and time settings are derived from the computer on which the base table structure (schema) was last updated.

For related information, see the topic "DateCreated, LastUpdated Properties" in DAO Help.

CDaoRecordset::GetDefaultDBName

Call this member function to determine the name of the database for this recordset.

virtual CString GetDefaultDBName();

Return Value

A CString that contains the path and name of the database from which this recordset is derived.

Remarks

If a recordset is created without a pointer to a CDaoDatabase, then this path is used by the recordset to open the default database. By default, this function returns an empty string. When ClassWizard derives a new recordset from CDaoRecordset, it will create this function for you.

The following example illustrates the use of the double backslash (\\) in the string, as is required for the string to be interpreted correctly.

CString CCustSet::GetDefaultDBName()
{
   return _T("c:\\mydir\\datasrc.mdb");
}

CDaoRecordset::GetDefaultSQL

The framework calls this member function to get the default SQL statement on which the recordset is based.

virtual CString GetDefaultSQL();

Return Value

A CString that contains the default SQL statement.

Remarks

This might be a table name or a SQL SELECT statement.

You indirectly define the default SQL statement by declaring your recordset class with ClassWizard, and ClassWizard performs this task for you.

If you pass a null SQL string to Open, then this function is called to determine the table name or SQL for your recordset.

CDaoRecordset::GetEditMode

Call this member function to determine the state of editing, which is one of the following values:

short GetEditMode();

Return Value

Returns a value that indicates the state of editing for the current record.

Remarks

Value Description
dbEditNone No editing operation is in progress.
dbEditInProgress Edit has been called.
dbEditAdd AddNew has been called.

For related information, see the topic "EditMode Property" in DAO Help.

CDaoRecordset::GetFieldCount

Call this member function to retrieve the number of fields (columns) defined in the recordset.

short GetFieldCount();

Return Value

The number of fields in the recordset.

Remarks

For related information, see the topic "Count Property" in DAO Help.

CDaoRecordset::GetFieldInfo

Call this member function to obtain information about the fields in a recordset.

void GetFieldInfo(
    int nIndex,  
    CDaoFieldInfo& fieldinfo,  
    DWORD dwInfoOptions = AFX_DAO_PRIMARY_INFO);

 
void GetFieldInfo(
    LPCTSTR lpszName,  
    CDaoFieldInfo& fieldinfo,  
    DWORD dwInfoOptions = AFX_DAO_PRIMARY_INFO);

Parameters

nIndex
The zero-based index of the predefined field in the recordset's Fields collection, for lookup by index.

fieldinfo
A reference to a CDaoFieldInfo structure.

dwInfoOptions
Options that specify which information about the recordset to retrieve. The available options are listed here along with what they cause the function to return. For best performance, retrieve only the level of information you need:

  • AFX_DAO_PRIMARY_INFO (Default) Name, Type, Size, Attributes

  • AFX_DAO_SECONDARY_INFO Primary information, plus: Ordinal Position, Required, Allow Zero Length, Collating Order, Foreign Name, Source Field, Source Table

  • AFX_DAO_ALL_INFO Primary and secondary information, plus: Default Value, Validation Rule, Validation Text

lpszName
The name of the field.

Remarks

One version of the function lets you look up a field by index. The other version lets you look up a field by name.

For a description of the information returned, see the CDaoFieldInfo structure. This structure has members that correspond to the items of information listed above in the description of dwInfoOptions. When you request information at one level, you get information for any prior levels as well.

For related information, see the topic "Attributes Property" in DAO Help.

CDaoRecordset::GetFieldValue

Call this member function to retrieve data in a recordset.

virtual void GetFieldValue(
    LPCTSTR lpszName,  
    COleVariant& varValue);

 
virtual void GetFieldValue(
    int nIndex,  
    COleVariant& varValue);
 
virtual COleVariant GetFieldValue(LPCTSTR lpszName); 
virtual COleVariant GetFieldValue(int nIndex);

Parameters

lpszName
A pointer to a string that contains the name of a field.

varValue
A reference to a COleVariant object that will store the value of a field.

nIndex
A zero-based index of the field in the recordset's Fields collection, for lookup by index.

Return Value

The two versions of GetFieldValue that return a value return a COleVariant object that contains the value of a field.

Remarks

You can look up a field by name or by ordinal position.

Note

It is more efficient to call one of the versions of this member function that takes a COleVariant object reference as a parameter, rather than calling a version that returns a COleVariant object. The latter versions of this function are kept for backward compatibility.

Use GetFieldValue and SetFieldValue to dynamically bind fields at run time rather than statically binding columns using the DoFieldExchange mechanism.

GetFieldValue and the DoFieldExchange mechanism can be combined to improve performance. For example, use GetFieldValue to retrieve a value that you need only on demand, and assign that call to a "More Information" button in the interface.

For related information, see the topics "Field Object" and "Value Property" in DAO Help.

CDaoRecordset::GetIndexCount

Call this member function to determine the number of indexes available on the table-type recordset.

short GetIndexCount();

Return Value

The number of indexes in the table-type recordset.

Remarks

GetIndexCount is useful for looping through all indexes in the recordset. For that purpose, use GetIndexCount in conjunction with GetIndexInfo. If you call this member function on dynaset-type or snapshot-type recordsets, MFC throws an exception.

For related information, see the topic "Attributes Property" in DAO Help.

CDaoRecordset::GetIndexInfo

Call this member function to obtain various kinds of information about an index defined in the base table underlying a recordset.

void GetIndexInfo(
    int nIndex,  
    CDaoIndexInfo& indexinfo,  
    DWORD dwInfoOptions = AFX_DAO_PRIMARY_INFO);

 
void GetIndexInfo(
    LPCTSTR lpszName,  
    CDaoIndexInfo& indexinfo,  
    DWORD dwInfoOptions = AFX_DAO_PRIMARY_INFO);

Parameters

nIndex
The zero-based index in the table's Indexes collection, for lookup by numerical position.

indexinfo
A reference to a CDaoIndexInfo structure.

dwInfoOptions
Options that specify which information about the index to retrieve. The available options are listed here along with what they cause the function to return. For best performance, retrieve only the level of information you need:

  • AFX_DAO_PRIMARY_INFO (Default) Name, Field Info, Fields

  • AFX_DAO_SECONDARY_INFO Primary information, plus: Primary, Unique, Clustered, IgnoreNulls, Required, Foreign

  • AFX_DAO_ALL_INFO Primary and secondary information, plus: Distinct Count

lpszName
A pointer to the name of the index object, for lookup by name.

Remarks

One version of the function lets you look up a index by its position in the collection. The other version lets you look up an index by name.

For a description of the information returned, see the CDaoIndexInfo structure. This structure has members that correspond to the items of information listed above in the description of dwInfoOptions. When you request information at one level, you get information for any prior levels as well.

For related information, see the topic "Attributes Property" in DAO Help.

CDaoRecordset::GetLastModifiedBookmark

Call this member function to retrieve the bookmark of the most recently added or updated record.

COleVariant GetLastModifiedBookmark();

Return Value

A COleVariant containing a bookmark that indicates the most recently added or changed record.

Remarks

When a recordset object is created or opened, each of its records already has a unique bookmark if it supports them. Call GetBookmark to determine if the recordset supports bookmarks. If the recordset does not support bookmarks, a CDaoException is thrown.

When you add a record, it appears at the end of the recordset, and is not the current record. To make the new record current, call GetLastModifiedBookmark and then call SetBookmark to return to the newly added record.

For related information, see the topic "LastModified Property" in DAO Help.

CDaoRecordset::GetLockingMode

Call this member function to determine the type of locking in effect for the recordset.

BOOL GetLockingMode();

Return Value

Nonzero if the type of locking is pessimistic, otherwise 0 for optimistic record locking.

Remarks

When pessimistic locking is in effect, the data page containing the record you are editing is locked as soon as you call the Edit member function. The page is unlocked when you call the Update or Close member function or any of the Move or Find operations.

When optimistic locking is in effect, the data page containing the record is locked only while the record is being updated with the Update member function.

When working with ODBC data sources, the locking mode is always optimistic.

For related information, see the topics "LockEdits Property" and "Locking Behavior in Multiuser Applications" in DAO Help.

CDaoRecordset::GetName

Call this member function to retrieve the name of the recordset.

CString GetName();

Return Value

A CString containing the name of the recordset.

Remarks

The name of the recordset must start with a letter and can contain a maximum of 40 characters. It can include numbers and underscore characters but can't include punctuation or spaces.

For related information, see the topic "Name Property" in DAO Help.

CDaoRecordset::GetParamValue

Call this member function to retrieve the current value of the specified parameter stored in the underlying DAOParameter object.

virtual COleVariant GetParamValue(int nIndex);  
virtual COleVariant GetParamValue(LPCTSTR lpszName);
```  
  
### Parameters  
 `nIndex`  
 The numerical position of the parameter in the underlying DAOParameter object.  
  
 `lpszName`  
 The name of the parameter whose value you want.  
  
### Return Value  
 An object of class [COleVariant](../Topic/COleVariant%20Class.md) that contains the parameter's value.  
  
### Remarks  
 You can access the parameter either by name or by its numerical position in the collection.  
  
 For related information, see the topic "Parameter Object" in DAO Help.  
  
##  <a name="cdaorecordset__getpercentposition"></a>  CDaoRecordset::GetPercentPosition  
 When working with a dynaset-type or snapshot-type recordset, if you call `GetPercentPosition` before fully populating the recordset, the amount of movement is relative to the number of records accessed as indicated by calling [GetRecordCount](#cdaorecordset__getrecordcount).  
  

float GetPercentPosition();

  
### Return Value  
 A number between 0 and 100 that indicates the approximate location of the current record in the recordset object based on a percentage of the records in the recordset.  
  
### Remarks  
 You can move to the last record by calling [MoveLast](#cdaorecordset__movelast) to complete the population of all recordsets, but this may take a significant amount of time.  
  
 You can call `GetPercentPosition` on all three types of recordset objects, including tables without indexes. However, you cannot call `GetPercentPosition` on forward-only scrolling snapshots, or on a recordset opened from a pass-through query against an external database. If there is no current record, or he current record has been deleted, a `CDaoException` is thrown.  
  
 For related information, see the topic "PercentPosition Property" in DAO Help.  
  
##  <a name="cdaorecordset__getrecordcount"></a>  CDaoRecordset::GetRecordCount  
 Call this member function to find out how many records in a recordset have been accessed.  
  

long GetRecordCount();

  
### Return Value  
 Returns the number of records accessed in a recordset object.  
  
### Remarks  
 `GetRecordCount` does not indicate how many records are contained in a dynaset-type or snapshot-type recordset until all records have been accessed. This member function call may take a significant amount of time to complete.  
  
 Once the last record has been accessed, the return value indicates the total number of undeleted records in the recordset. To force the last record to be accessed, call the `MoveLast` or `FindLast` member function for the recordset. You can also use a SQL Count to determine the approximate number of records your query will return.  
  
 As your application deletes records in a dynaset-type recordset, the return value of `GetRecordCount` decreases. However, records deleted by other users are not reflected by `GetRecordCount` until the current record is positioned to a deleted record. If you execute a transaction that affects the record count and subsequently roll back the transaction, `GetRecordCount` will not reflect the actual number of remaining records.  
  
 The value of `GetRecordCount` from a snapshot-type recordset is not affected by changes in the underlying tables.  
  
 The value of `GetRecordCount` from a table-type recordset reflects the approximate number of records in the table and is affected immediately as table records are added and deleted.  
  
 A recordset with no records returns a value of 0. When working with attached tables or ODBC databases, `GetRecordCount` always returns – 1. Calling the **Requery** member function on a recordset resets the value of `GetRecordCount` just as if the query were re-executed.  
  
 For related information, see the topic "RecordCount Property" in DAO Help.  
  
##  <a name="cdaorecordset__getsql"></a>  CDaoRecordset::GetSQL  
 Call this member function to get the SQL statement that was used to select the recordset's records when it was opened.  
  

CString GetSQL() const;

  
### Return Value  
 A `CString` that contains the SQL statement.  
  
### Remarks  
 This will generally be a SQL **SELECT** statement.  
  
 The string returned by `GetSQL` is typically different from any string you may have passed to the recordset in the `lpszSQL` parameter to the [Open](#cdaorecordset__open) member function. This is because the recordset constructs a full SQL statement based on what you passed to **Open**, what you specified with ClassWizard, and what you may have specified in the [m_strFilter](#cdaorecordset__m_strfilter) and [m_strSort](#cdaorecordset__m_strsort) data members.  
  
> [!NOTE]
>  Call this member function only after calling **Open**.  
  
 For related information, see the topic "SQL Property" in DAO Help.  
  
##  <a name="cdaorecordset__gettype"></a>  CDaoRecordset::GetType  
 Call this member function after opening the recordset to determine the type of the recordset object.  
  

short GetType();

  
### Return Value  
 One of the following values that indicates the type of a recordset:  
  
- **dbOpenTable** Table-type recordset  
  
- **dbOpenDynaset** Dynaset-type recordset  
  
- **dbOpenSnapshot** Snapshot-type recordset  
  
### Remarks  
 For related information, see the topic "Type Property" in DAO Help.  
  
##  <a name="cdaorecordset__getvalidationrule"></a>  CDaoRecordset::GetValidationRule  
 Call this member function to determine the rule used to validate data.  
  

CString GetValidationRule();

  
### Return Value  
 A `CString` object containing a value that validates the data in a record as it is changed or added to a table.  
  
### Remarks  
 This rule is text-based, and is applied each time the underlying table is changed. If the data is not legal, MFC throws an exception. The returned error message is the text of the ValidationText property of the underlying field object, if specified, or the text of the expression specified by the ValidationRule property of the underlying field object. You can call [GetValidationText](#cdaorecordset__getvalidationtext) to obtain the text of the error message.  
  
 For example, a field in a record that requires the day of the month might have a validation rule such as "DAY BETWEEN 1 AND 31."  
  
 For related information, see the topic "ValidationRule Property" in DAO Help.  
  
##  <a name="cdaorecordset__getvalidationtext"></a>  CDaoRecordset::GetValidationText  
 Call this member function to retrieve the text of the ValidationText property of the underlying field object.  
  

CString GetValidationText();

  
### Return Value  
 A `CString` object containing the text of the message that is displayed if the value of a field does not satisfy the validation rule of the underlying field object.  
  
### Remarks  
 For related information, see the topic "ValidationText Property" in DAO Help.  
  
##  <a name="cdaorecordset__isbof"></a>  CDaoRecordset::IsBOF  
 Call this member function before you scroll from record to record to learn whether you have gone before the first record of the recordset.  
  

BOOL IsBOF() const;

  
### Return Value  
 Nonzero if the recordset contains no records or if you have scrolled backward before the first record; otherwise 0.  
  
### Remarks  
 You can also call `IsBOF` along with `IsEOF` to determine whether the recordset contains any records or is empty. Immediately after you call **Open**, if the recordset contains no records, `IsBOF` returns nonzero. When you open a recordset that has at least one record, the first record is the current record and `IsBOF` returns 0.  
  
 If the first record is the current record and you call `MovePrev`, `IsBOF` will subsequently return nonzero. If `IsBOF` returns nonzero and you call `MovePrev`, an exception is thrown. If `IsBOF` returns nonzero, the current record is undefined, and any action that requires a current record will result in an exception.  
  
 Effect of specific methods on `IsBOF` and `IsEOF` settings:  
  
-  Calling **Open** internally makes the first record in the recordset the current record by calling **MoveFirst**. Therefore, calling **Open** on an empty set of records causes `IsBOF` and `IsEOF` to return nonzero. (See the following table for the behavior of a failed **MoveFirst** or `MoveLast` call.)  
  
-  All Move operations that successfully locate a record cause both `IsBOF` and `IsEOF` to return 0.  
  
-  An `AddNew` call followed by an **Update** call that successfully inserts a new record will cause `IsBOF` to return 0, but only if `IsEOF` is already nonzero. The state of `IsEOF` will always remain unchanged. As defined by the Microsoft Jet database engine, the current record pointer of an empty recordset is at the end of a file, so any new record is inserted after the current record.  
  
-  Any **Delete** call, even if it removes the only remaining record from a recordset, will not change the value of `IsBOF` or `IsEOF`.  
  
 This table shows which Move operations are allowed with different combinations of `IsBOF`/ `IsEOF`.  
  
||MoveFirst, MoveLast|MovePrev,<br /><br /> Move < 0|Move 0|MoveNext,<br /><br /> Move > 0|  
|------|-------------------------|-----------------------------|------------|-----------------------------|  
|`IsBOF`=nonzero,<br /><br /> `IsEOF`=0|Allowed|Exception|Exception|Allowed|  
|`IsBOF`=0,<br /><br /> `IsEOF`=nonzero|Allowed|Allowed|Exception|Exception|  
|Both nonzero|Exception|Exception|Exception|Exception|  
|Both 0|Allowed|Allowed|Allowed|Allowed|  
  
 Allowing a Move operation does not mean that the operation will successfully locate a record. It merely indicates that an attempt to perform the specified Move operation is allowed and will not generate an exception. The value of the `IsBOF` and `IsEOF` member functions may change as a result of the attempted move.  
  
 The effect of Move operations that do not locate a record on the value of `IsBOF` and `IsEOF` settings is shown in the following table.  
  
||IsBOF|IsEOF|  
|------|-----------|-----------|  
|**MoveFirst**, `MoveLast`|Nonzero|Nonzero|  
|**Move** 0|No change|No change|  
|`MovePrev`, **Move** < 0|Nonzero|No change|  
|`MoveNext`, **Move** > 0|No change|Nonzero|  
  
 For related information, see the topic "BOF, EOF Properties" in DAO Help.  
  
##  <a name="cdaorecordset__isdeleted"></a>  CDaoRecordset::IsDeleted  
 Call this member function to determine whether the current record has been deleted.  
  

BOOL IsDeleted() const;

  
### Return Value  
 Nonzero if the recordset is positioned on a deleted record; otherwise 0.  
  
### Remarks  
 If you scroll to a record and `IsDeleted` returns **TRUE** (nonzero), then you must scroll to another record before you can perform any other recordset operations.  
  
> [!NOTE]
>  You don't need to check the deleted status for records in a snapshot or table-type recordset. Because records cannot be deleted from a snapshot, there is no need to call `IsDeleted`. For table-type recordsets, deleted records are actually removed from the recordset. Once a record has been deleted, either by you, another user, or in another recordset, you cannot scroll back to that record. Therefore, there is no need to call `IsDeleted`.  
  
 When you delete a record from a dynaset, it is removed from the recordset and you cannot scroll back to that record. However, if a record in a dynaset is deleted either by another user or in another recordset based on the same table, `IsDeleted` will return **TRUE** when you later scroll to that record.  
  
 For related information, see the topics "Delete Method", "LastModified Property", and "EditMode Property" in DAO Help.  
  
##  <a name="cdaorecordset__iseof"></a>  CDaoRecordset::IsEOF  
 Call this member function as you scroll from record to record to learn whether you have gone beyond the last record of the recordset.  
  

BOOL IsEOF() const;

  
### Return Value  
 Nonzero if the recordset contains no records or if you have scrolled beyond the last record; otherwise 0.  
  
### Remarks  
 You can also call `IsEOF` to determine whether the recordset contains any records or is empty. Immediately after you call **Open**, if the recordset contains no records, `IsEOF` returns nonzero. When you open a recordset that has at least one record, the first record is the current record and `IsEOF` returns 0.  
  
 If the last record is the current record when you call `MoveNext`, `IsEOF` will subsequently return nonzero. If `IsEOF` returns nonzero and you call `MoveNext`, an exception is thrown. If `IsEOF` returns nonzero, the current record is undefined, and any action that requires a current record will result in an exception.  
  
 Effect of specific methods on `IsBOF` and `IsEOF` settings:  
  
-  Calling **Open** internally makes the first record in the recordset the current record by calling **MoveFirst**. Therefore, calling **Open** on an empty set of records causes `IsBOF` and `IsEOF` to return nonzero. (See the following table for the behavior of a failed **MoveFirst** call.)  
  
-  All Move operations that successfully locate a record cause both `IsBOF` and `IsEOF` to return 0.  
  
-  An `AddNew` call followed by an **Update** call that successfully inserts a new record will cause `IsBOF` to return 0, but only if `IsEOF` is already nonzero. The state of `IsEOF` will always remain unchanged. As defined by the Microsoft Jet database engine, the current record pointer of an empty recordset is at the end of a file, so any new record is inserted after the current record.  
  
-  Any **Delete** call, even if it removes the only remaining record from a recordset, will not change the value of `IsBOF` or `IsEOF`.  
  
 This table shows which Move operations are allowed with different combinations of `IsBOF`/ `IsEOF`.  
  
||MoveFirst, MoveLast|MovePrev,<br /><br /> Move < 0|Move 0|MoveNext,<br /><br /> Move > 0|  
|------|-------------------------|-----------------------------|------------|-----------------------------|  
|`IsBOF`=nonzero,<br /><br /> `IsEOF`=0|Allowed|Exception|Exception|Allowed|  
|`IsBOF`=0,<br /><br /> `IsEOF`=nonzero|Allowed|Allowed|Exception|Exception|  
|Both nonzero|Exception|Exception|Exception|Exception|  
|Both 0|Allowed|Allowed|Allowed|Allowed|  
  
 Allowing a Move operation does not mean that the operation will successfully locate a record. It merely indicates that an attempt to perform the specified Move operation is allowed and will not generate an exception. The value of the `IsBOF` and `IsEOF` member functions may change as a result of the attempted Move.  
  
 The effect of Move operations that do not locate a record on the value of `IsBOF` and `IsEOF` settings is shown in the following table.  
  
||IsBOF|IsEOF|  
|------|-----------|-----------|  
|**MoveFirst**, `MoveLast`|Nonzero|Nonzero|  
|**Move** 0|No change|No change|  
|`MovePrev`, **Move** < 0|Nonzero|No change|  
|`MoveNext`, **Move** > 0|No change|Nonzero|  
  
 For related information, see the topic "BOF, EOF Properties" in DAO Help.  
  
##  <a name="cdaorecordset__isfielddirty"></a>  CDaoRecordset::IsFieldDirty  
 Call this member function to determine whether the specified field data member of a dynaset has been flagged as "dirty" (changed).  
  

BOOL IsFieldDirty(void* pv);

  
### Parameters  
 `pv`  
 A pointer to the field data member whose status you want to check, or **NULL** to determine if any of the fields are dirty.  
  
### Return Value  
 Nonzero if the specified field data member is flagged as dirty; otherwise 0.  
  
### Remarks  
 The data in all dirty field data members will be transferred to the record on the data source when the current record is updated by a call to the **Update** member function of `CDaoRecordset` (following a call to **Edit** or `AddNew`). With this knowledge, you can take further steps, such as unflagging the field data member to mark the column so it will not be written to the data source.  
  
 `IsFieldDirty` is implemented through `DoFieldExchange`.  
  
##  <a name="cdaorecordset__isfieldnull"></a>  CDaoRecordset::IsFieldNull  
 Call this member function to determine whether the specified field data member of a recordset has been flagged as Null.  
  

BOOL IsFieldNull(void* pv);

  
### Parameters  
 `pv`  
 A pointer to the field data member whose status you want to check, or **NULL** to determine if any of the fields are Null.  
  
### Return Value  
 Nonzero if the specified field data member is flagged as Null; otherwise 0.  
  
### Remarks  
 (In database terminology, Null means "having no value" and is not the same as **NULL** in C++.) If a field data member is flagged as Null, it is interpreted as a column of the current record for which there is no value.  
  
> [!NOTE]
>  In certain situations, using `IsFieldNull` can be inefficient, as the following code example illustrates:  
  
 [!CODE [NVC_MFCDatabase#5](../CodeSnippet/VS_Snippets_Cpp/NVC_MFCDatabase#5)]  
  
> [!NOTE]
>  If you are using dynamic record binding, without deriving from `CDaoRecordset`, be sure to use **VT_NULL** as shown in the example.  
  
##  <a name="cdaorecordset__isfieldnullable"></a>  CDaoRecordset::IsFieldNullable  
 Call this member function to determine whether the specified field data member is "nullable" (can be set to a Null value; C++ **NULL** is not the same as Null, which, in database terminology, means "having no value").  
  

BOOL IsFieldNullable(void* pv);

  
### Parameters  
 `pv`  
 A pointer to the field data member whose status you want to check, or **NULL** to determine if any of the fields are Null.  
  
### Return Value  
 Nonzero if the specified field data member can be made Null; otherwise 0.  
  
### Remarks  
 A field that cannot be Null must have a value. If you attempt to set such a field to Null when adding or updating a record, the data source rejects the addition or update, and **Update** will throw an exception. The exception occurs when you call **Update**, not when you call `SetFieldNull`.  
  
##  <a name="cdaorecordset__isopen"></a>  CDaoRecordset::IsOpen  
 Call this member function to determine if the recordset is open.  
  

BOOL IsOpen() const;

  
### Return Value  
 Nonzero if the recordset object's **Open** or **Requery** member function has previously been called and the recordset has not been closed; otherwise 0.  
  
### Remarks  
  
##  <a name="cdaorecordset__m_bcheckcachefordirtyfields"></a>  CDaoRecordset::m_bCheckCacheForDirtyFields  
 Contains a flag indicating whether cached fields are automatically marked as dirty (changed) and Null.  
  
### Remarks  
 The flag defaults to **TRUE**. The setting in this data member controls the entire double-buffering mechanism. If you set the flag to **TRUE**, you can turn off the caching on a field-by-field basis using the DFX mechanism. If you set the flag to **FALSE**, you must call `SetFieldDirty` and `SetFieldNull` yourself.  
  
 Set this data member before calling **Open**. This mechanism is primarily for ease-of-use. Performance may be slower because of the double-buffering of fields as changes are made.  
  
##  <a name="cdaorecordset__m_nfields"></a>  CDaoRecordset::m_nFields  
 Contains the number of field data members in the recordset class and the number of columns selected by the recordset from the data source.  
  
### Remarks  
 The constructor for the recordset class must initialize `m_nFields` with the correct number of statically bound fields. ClassWizard writes this initialization for you when you use it to declare your recordset class. You can also write it manually.  
  
 The framework uses this number to manage interaction between the field data members and the corresponding columns of the current record on the data source.  
  
> [!NOTE]
>  This number must correspond to the number of output columns registered in `DoFieldExchange` after a call to `SetFieldType` with the parameter **CDaoFieldExchange::outputColumn**.  
  
 You can bind columns dynamically by way of `CDaoRecordset::GetFieldValue` and `CDaoRecordset::SetFieldValue`. If you do so, you do not need to increment the count in `m_nFields` to reflect the number of DFX function calls in your `DoFieldExchange` member function.  
  
##  <a name="cdaorecordset__m_nparams"></a>  CDaoRecordset::m_nParams  
 Contains the number of parameter data members in the recordset class — the number of parameters passed with the recordset's query.  
  
### Remarks  
 If your recordset class has any parameter data members, the constructor for the class must initialize `m_nParams` with the correct number. The value of `m_nParams` defaults to 0. If you add parameter data members — which you must do manually — you must also manually add an initialization in the class constructor to reflect the number of parameters (which must be at least as large as the number of '' placeholders in your **m_strFilter** or `m_strSort` string).  
  
 The framework uses this number when it parameterizes the recordset's query.  
  
> [!NOTE]
>  This number must correspond to the number of "params" registered in `DoFieldExchange` after a call to `SetFieldType` with the parameter **CFieldExchange::param**.  
  
 For related information, see the topic "Parameter Object" in DAO Help.  
  
##  <a name="cdaorecordset__m_pdaorecordset"></a>  CDaoRecordset::m_pDAORecordset  
 Contains a pointer to the OLE interface for the DAO recordset object underlying the `CDaoRecordset` object.  
  
### Remarks  
 Use this pointer if you need to access the DAO interface directly.  
  
 For related information, see the topic "Recordset Object" in DAO Help.  
  
##  <a name="cdaorecordset__m_pdatabase"></a>  CDaoRecordset::m_pDatabase  
 Contains a pointer to the `CDaoDatabase` object through which the recordset is connected to a data source.  
  
### Remarks  
 This variable is set in two ways. Typically, you pass a pointer to an already open `CDaoDatabase` object when you construct the recordset object. If you pass **NULL** instead, **CDaoRecordset** creates a `CDaoDatabase` object for you and opens it. In either case, `CDaoRecordset` stores the pointer in this variable.  
  
 Normally you will not directly need to use the pointer stored in **m_pDatabase**. If you write your own extensions to `CDaoRecordset`, however, you might need to use the pointer. For example, you might need the pointer if you throw your own `CDaoException`(s).  
  
 For related information, see the topic "Database Object" in DAO Help.  
  
##  <a name="cdaorecordset__m_strfilter"></a>  CDaoRecordset::m_strFilter  
 Contains a string that is used to construct the **WHERE** clause of a SQL statement.  
  
### Remarks  
 It does not include the reserved word **WHERE** to filter the recordset. The use of this data member is not applicable to table-type recordsets. The use of **m_strFilter** has no effect when opening a recordset using a `CDaoQueryDef` pointer.  
  
 Use the U.S. date format (month-day-year) when you filter fields containing dates, even if you are not using the U.S. version of the Microsoft Jet database engine; otherwise, the data may not be filtered as you expect.  
  
 For related information, see the topic "Filter Property" in DAO Help.  
  
##  <a name="cdaorecordset__m_strsort"></a>  CDaoRecordset::m_strSort  
 Contains a string containing the **ORDERBY** clause of a SQL statement without the reserved words **ORDERBY**.  
  
### Remarks  
 You can sort on dynaset- and snapshot-type recordset objects.  
  
 You cannot sort table-type recordset objects. To determine the sort order of a table-type recordset, call [SetCurrentIndex](#cdaorecordset__setcurrentindex).  
  
 The use of `m_strSort` has no effect when opening a recordset using a `CDaoQueryDef` pointer.  
  
 For related information, see the topic "Sort Property" in DAO Help.  
  
##  <a name="cdaorecordset__move"></a>  CDaoRecordset::Move  
 Call this member function to position the recordset `lRows` records from the current record.  
  

virtual void Move(long lRows);

  
### Parameters  
 `lRows`  
 The number of records to move forward or backward. Positive values move forward, toward the end of the recordset. Negative values move backward, toward the beginning.  
  
### Remarks  
 You can move forward or backward. `Move( 1 )` is equivalent to `MoveNext`, and `Move( -1 )` is equivalent to `MovePrev`.  
  
> [!CAUTION]
>  Calling any of the **Move** functions throws an exception if the recordset has no records. In general, call both `IsBOF` and `IsEOF` before a Move operation to determine whether the recordset has any records. After you call **Open** or **Requery**, call either `IsBOF` or `IsEOF`.  
  
> [!NOTE]
>  If you have scrolled past the beginning or end of the recordset ( `IsBOF` or `IsEOF` returns nonzero), a call to **Move** throws a `CDaoException`.  
  
> [!NOTE]
>  If you call any of the **Move** functions while the current record is being updated or added, the updates are lost without warning.  
  
 When you call **Move** on a forward-only scrolling snapshot, the `lRows` parameter must be a positive integer and bookmarks are not allowed, so you can move forward only.  
  
 To make the first, last, next, or previous record in a recordset the current record, call the **MoveFirst**, `MoveLast`, `MoveNext`, or `MovePrev` member function.  
  
 For related information, see the topics "Move Method" and "MoveFirst, MoveLast, MoveNext, MovePrevious Methods" in DAO Help.  
  
##  <a name="cdaorecordset__movefirst"></a>  CDaoRecordset::MoveFirst  
 Call this member function to make the first record in the recordset (if any) the current record.  
  

void MoveFirst();

  
### Remarks  
 You do not have to call **MoveFirst** immediately after you open the recordset. At that time, the first record (if any) is automatically the current record.  
  
> [!CAUTION]
>  Calling any of the **Move** functions throws an exception if the recordset has no records. In general, call both `IsBOF` and `IsEOF` before a Move operation to determine whether the recordset has any records. After you call **Open** or **Requery**, call either `IsBOF` or `IsEOF`.  
  
> [!NOTE]
>  If you call any of the **Move** functions while the current record is being updated or added, the updates are lost without warning.  
  
 Use the **Move** functions to move from record to record without applying a condition. Use the Find operations to locate records in a dynaset-type or snapshot-type recordset object that satisfy a certain condition. To locate a record in a table-type recordset object, call `Seek`.  
  
 If the recordset refers to a table-type recordset, movement follows the table's current index. You can set the current index by using the Index property of the underlying DAO object. If you do not set the current index, the order of returned records is undefined.  
  
 If you call `MoveLast` on a recordset object based on a SQL query or querydef, the query is forced to completion and the recordset object is fully populated.  
  
 You cannot call the **MoveFirst** or `MovePrev` member function with a forward-only scrolling snapshot.  
  
 To move the position of the current record in a recordset object a specific number of records forward or backward, call **Move**.  
  
 For related information, see the topics "Move Method" and "MoveFirst, MoveLast, MoveNext, MovePrevious Methods" in DAO Help.  
  
##  <a name="cdaorecordset__movelast"></a>  CDaoRecordset::MoveLast  
 Call this member function to make the last record (if any) in the recordset the current record.  
  

void MoveLast();

  
### Remarks  
  
> [!CAUTION]
>  Calling any of the **Move** functions throws an exception if the recordset has no records. In general, call both `IsBOF` and `IsEOF` before a Move operation to determine whether the recordset has any records. After you call **Open** or **Requery**, call either `IsBOF` or `IsEOF`.  
  
> [!NOTE]
>  If you call any of the **Move** functions while the current record is being updated or added, the updates are lost without warning.  
  
 Use the **Move** functions to move from record to record without applying a condition. Use the Find operations to locate records in a dynaset-type or snapshot-type recordset object that satisfy a certain condition. To locate a record in a table-type recordset object, call `Seek`.  
  
 If the recordset refers to a table-type recordset, movement follows the table's current index. You can set the current index by using the Index property of the underlying DAO object. If you do not set the current index, the order of returned records is undefined.  
  
 If you call `MoveLast` on a recordset object based on a SQL query or querydef, the query is forced to completion and the recordset object is fully populated.  
  
 To move the position of the current record in a recordset object a specific number of records forward or backward, call **Move**.  
  
 For related information, see the topics "Move Method" and "MoveFirst, MoveLast, MoveNext, MovePrevious Methods" in DAO Help.  
  
##  <a name="cdaorecordset__movenext"></a>  CDaoRecordset::MoveNext  
 Call this member function to make the next record in the recordset the current record.  
  

void MoveNext();

  
### Remarks  
 It is recommended that you call `IsBOF` before you attempt to move to the previous record. A call to `MovePrev` will throw a `CDaoException` if `IsBOF` returns nonzero, indicating either that you have already scrolled before the first record or that no records were selected by the recordset.  
  
> [!CAUTION]
>  Calling any of the **Move** functions throws an exception if the recordset has no records. In general, call both `IsBOF` and `IsEOF` before a Move operation to determine whether the recordset has any records. After you call **Open** or **Requery**, call either `IsBOF` or `IsEOF`.  
  
> [!NOTE]
>  If you call any of the **Move** functions while the current record is being updated or added, the updates are lost without warning.  
  
 Use the **Move** functions to move from record to record without applying a condition. Use the Find operations to locate records in a dynaset-type or snapshot-type recordset object that satisfy a certain condition. To locate a record in a table-type recordset object, call `Seek`.  
  
 If the recordset refers to a table-type recordset, movement follows the table's current index. You can set the current index by using the Index property of the underlying DAO object. If you do not set the current index, the order of returned records is undefined.  
  
 To move the position of the current record in a recordset object a specific number of records forward or backward, call **Move**.  
  
 For related information, see the topics "Move Method" and "MoveFirst, MoveLast, MoveNext, MovePrevious Methods" in DAO Help.  
  
##  <a name="cdaorecordset__moveprev"></a>  CDaoRecordset::MovePrev  
 Call this member function to make the previous record in the recordset the current record.  
  

void MovePrev();

  
### Remarks  
 It is recommended that you call `IsBOF` before you attempt to move to the previous record. A call to `MovePrev` will throw a `CDaoException` if `IsBOF` returns nonzero, indicating either that you have already scrolled before the first record or that no records were selected by the recordset.  
  
> [!CAUTION]
>  Calling any of the **Move** functions throws an exception if the recordset has no records. In general, call both `IsBOF` and `IsEOF` before a Move operation to determine whether the recordset has any records. After you call **Open** or **Requery**, call either `IsBOF` or `IsEOF`.  
  
> [!NOTE]
>  If you call any of the **Move** functions while the current record is being updated or added, the updates are lost without warning.  
  
 Use the **Move** functions to move from record to record without applying a condition. Use the Find operations to locate records in a dynaset-type or snapshot-type recordset object that satisfy a certain condition. To locate a record in a table-type recordset object, call `Seek`.  
  
 If the recordset refers to a table-type recordset, movement follows the table's current index. You can set the current index by using the Index property of the underlying DAO object. If you do not set the current index, the order of returned records is undefined.  
  
 You cannot call the **MoveFirst** or `MovePrev` member function with a forward-only scrolling snapshot.  
  
 To move the position of the current record in a recordset object a specific number of records forward or backward, call **Move**.  
  
 For related information, see the topics "Move Method" and "MoveFirst, MoveLast, MoveNext, MovePrevious Methods" in DAO Help.  
  
##  <a name="cdaorecordset__open"></a>  CDaoRecordset::Open  
 You must call this member function to retrieve the records for the recordset.  
  

virtual void Open( int nOpenType = AFX_DAO_USE_DEFAULT_TYPE,
LPCTSTR lpszSQL = NULL,
int nOptions = 0);

virtual void Open( CDaoTableDef* pTableDef,
int nOpenType = dbOpenTable,
int nOptions = 0);

virtual void Open( CDaoQueryDef* pQueryDef,
int nOpenType = dbOpenDynaset,
int nOptions = 0);

  
### Parameters  
 `nOpenType`  
 One of the following values:  
  
- **dbOpenDynaset** A dynaset-type recordset with bidirectional scrolling. This is the default.  
  
- **dbOpenTable** A table-type recordset with bidirectional scrolling.  
  
- **dbOpenSnapshot** A snapshot-type recordset with bidirectional scrolling.  
  
 `lpszSQL`  
 A string pointer containing one of the following:  
  
-  A **NULL** pointer.  
  
-  The name of one or more tabledefs and/or querydefs (comma-separated).  
  
-  A SQL **SELECT** statement (optionally with a SQL **WHERE** or **ORDERBY** clause).  
  
-  A pass-through query.  
  
 `nOptions`  
 One or more of the options listed below. The default value is 0. Possible values are as follows:  
  
- **dbAppendOnly** You can only append new records (dynaset-type recordset only). This option means literally that records may only be appended. The MFC ODBC database classes have an append-only option that allows records to be retrieved and appended.  
  
- **dbForwardOnly** The recordset is a forward-only scrolling snapshot.  
  
- **dbSeeChanges** Generate an exception if another user is changing data you are editing.  
  
- **dbDenyWrite** Other users cannot modify or add records.  
  
- **dbDenyRead** Other users cannot view records (table-type recordset only).  
  
- **dbReadOnly** You can only view records; other users can modify them.  
  
- **dbInconsistent** Inconsistent updates are allowed (dynaset-type recordset only).  
  
- **dbConsistent** Only consistent updates are allowed (dynaset-type recordset only).  
  
> [!NOTE]
>  The constants **dbConsistent** and **dbInconsistent** are mutually exclusive. You can use one or the other, but not both in a given instance of **Open**.  
  
 *pTableDef*  
 A pointer to a [CDaoTableDef](../Topic/CDaoTableDef%20Class.md) object. This version is valid only for table-type recordsets. When using this option, the `CDaoDatabase` pointer used to construct the `CDaoRecordset` is not used; rather, the database in which the tabledef resides is used.  
  
 *pQueryDef*  
 A pointer to a [CDaoQueryDef](../Topic/CDaoQueryDef%20Class.md) object. This version is valid only for dynaset-type and snapshot-type recordsets. When using this option, the `CDaoDatabase` pointer used to construct the `CDaoRecordset` is not used; rather, the database in which the querydef resides is used.  
  
### Remarks  
 Before calling **Open**, you must construct the recordset object. There are several ways to do this:  
  
-  When you construct the recordset object, pass a pointer to a `CDaoDatabase` object that is already open.  
  
-  When you construct the recordset object, pass a pointer to a `CDaoDatabase` object that is not open. The recordset opens a `CDaoDatabase` object, but will not close it when the recordset object closes.  
  
-  When you construct the recordset object, pass a **NULL** pointer. The recordset object calls `GetDefaultDBName` to get the name of the Microsoft Access .MDB file to open. The recordset then opens a `CDaoDatabase` object and keeps it open as long as the recordset is open. When you call **Close** on the recordset, the `CDaoDatabase` object is also closed.  
  
    > [!NOTE]
    >  When the recordset opens the `CDaoDatabase` object, it opens the data source with nonexclusive access.  
  
 For the version of **Open** that uses the `lpszSQL` parameter, once the recordset is open you can retrieve records in one of several ways. The first option is to have DFX functions in your `DoFieldExchange`. The second option is to use dynamic binding by calling the `GetFieldValue` member function. These options can be implemented separately or in combination. If they are combined, you will have to pass in the SQL statement yourself on the call to **Open**.  
  
 When you use the second version of **Open** where you pass in a `CDaoTableDef` object, the resulting columns will be available for you to bind via `DoFieldExchange` and the DFX mechanism, and/or bind dynamically via `GetFieldValue`.  
  
> [!NOTE]
>  You can only call **Open** using a `CDaoTableDef` object for table-type recordsets.  
  
 When you use the third version of **Open** where you pass in a `CDaoQueryDef` object, that query will be executed, and the resulting columns will be available for you to bind via `DoFieldExchange` and the DFX mechanism, and/or bind dynamically via `GetFieldValue`.  
  
> [!NOTE]
>  You can only call **Open** using a `CDaoQueryDef` object for dynaset-type and snapshot-type recordsets.  
  
 For the first version of **Open** that uses the `lpszSQL` parameter, records are selected based on criteria shown in the following table.  
  
|Value of the `lpszSQL` parameter|Records selected are determined by|Example|  
|--------------------------------------|----------------------------------------|-------------|  
|**NULL**|The string returned by `GetDefaultSQL`.||  
|A comma-separated list of one or more tabledefs and/or querydef names.|All columns represented in the `DoFieldExchange`.|`"Customer"`|  
|**SELECT** column-list **FROM** table-list|The specified columns from the specified tabledef(s) and/or querydef(s).|`"SELECT CustId, CustName`<br /><br /> `FROM Customer"`|  
  
 The usual procedure is to pass **NULL** to **Open**; in that case, **Open** calls `GetDefaultSQL`, an overridable member function that ClassWizard generates when creating a `CDaoRecordset`-derived class. This value gives the tabledef(s) and/or querydef name(s) you specified in ClassWizard. You can instead specify other information in the `lpszSQL` parameter.  
  
 Whatever you pass, **Open** constructs a final SQL string for the query (the string may have SQL **WHERE** and **ORDERBY** clauses appended to the `lpszSQL` string you passed) and then executes the query. You can examine the constructed string by calling `GetSQL` after calling **Open**.  
  
 The field data members of your recordset class are bound to the columns of the data selected. If any records are returned, the first record becomes the current record.  
  
 If you want to set options for the recordset, such as a filter or sort, set `m_strSort` or **m_strFilter** after you construct the recordset object but before you call **Open**. If you want to refresh the records in the recordset after the recordset is already open, call **Requery**.  
  
 If you call **Open** on a dynaset-type or snapshot-type recordset, or if the data source refers to a SQL statement or a tabledef that represents an attached table, you cannot use **dbOpenTable** for the type argument; if you do, MFC throws an exception. To determine whether a tabledef object represents an attached table, create a [CDaoTableDef](../Topic/CDaoTableDef%20Class.md) object and call its [GetConnect](../Topic/CDaoTableDef%20Class.md#cdaotabledef__getconnect) member function.  
  
 Use the **dbSeeChanges** flag if you wish to trap changes made by another user or another program on your machine when you are editing or deleting the same record. For example, if two users start editing the same record, the first user to call the **Update** member function succeeds. When **Update** is called by the second user, a `CDaoException` is thrown. Similarly, if the second user tries to call **Delete** to delete the record, and it has already been changed by the first user, a `CDaoException` occurs.  
  
 Typically, if the user gets this `CDaoException` while updating, your code should refresh the contents of the fields and retrieve the newly modified values. If the exception occurs in the process of deleting, your code could display the new record data to the user and a message indicating that the data has recently changed. At this point, your code can request a confirmation that the user still wants to delete the record.  
  
> [!TIP]
>  Use the forward-only scrolling option ( **dbForwardOnly**) to improve performance when your application makes a single pass through a recordset opened from an ODBC data source.  
  
 For related information, see the topic "OpenRecordset Method" in DAO Help.  
  
##  <a name="cdaorecordset__requery"></a>  CDaoRecordset::Requery  
 Call this member function to rebuild (refresh) a recordset.  
  

virtual void Requery();

  
### Remarks  
 If any records are returned, the first record becomes the current record.  
  
 In order for the recordset to reflect the additions and deletions that you or other users are making to the data source, you must rebuild the recordset by calling **Requery**. If the recordset is a dynaset, it automatically reflects updates that you or other users make to its existing records (but not additions). If the recordset is a snapshot, you must call **Requery** to reflect edits by other users as well as additions and deletions.  
  
 For either a dynaset or a snapshot, call **Requery** any time you want to rebuild the recordset using parameter values. Set the new filter or sort by setting [m_strFilter](#cdaorecordset__m_strfilter) and [m_strSort](#cdaorecordset__m_strsort) before calling **Requery**. Set new parameters by assigning new values to parameter data members before calling **Requery**.  
  
 If the attempt to rebuild the recordset fails, the recordset is closed. Before you call **Requery**, you can determine whether the recordset can be requeried by calling the [CanRestart](#cdaorecordset__canrestart) member function. `CanRestart` does not guarantee that **Requery** will succeed.  
  
> [!CAUTION]
>  Call **Requery** only after you have called **Open**.  
  
> [!NOTE]
>  Calling [Requery](#cdaorecordset__requery) changes DAO bookmarks.  
  
 You can't call **Requery** on a dynaset-type or snapshot-type recordset if calling `CanRestart` returns 0, nor can you use it on a table-type recordset.  
  
 If both `IsBOF` and `IsEOF` return nonzero after you call **Requery**, the query didn't return any records and the recordset will contain no data.  
  
 For related information, see the topic "Requery Method" in DAO Help.  
  
##  <a name="cdaorecordset__seek"></a>  CDaoRecordset::Seek  
 Call this member function to locate the record in an indexed table-type recordset object that satisfies the specified criteria for the current index and make that record the current record.  
  

BOOL Seek( LPCTSTR lpszComparison,
COleVariant* pKey1,
COleVariant* pKey2 = NULL,
COleVariant* pKey3 = NULL);

BOOL Seek( LPCTSTR lpszComparison,
COleVariant* pKeyArray,
WORD nKeys);

  
### Parameters  
 `lpszComparison`  
 One of the following string expressions: "<", "<=", "=", ">=", or ">".  
  
 `pKey1`  
 A pointer to a [COleVariant](../Topic/COleVariant%20Class.md) whose value corresponds to the first field in the index. Required.  
  
 *pKey2*  
 A pointer to a `COleVariant` whose value corresponds to the second field in the index, if any. Defaults to **NULL**.  
  
 *pKey3*  
 A pointer to a `COleVariant` whose value corresponds to the third field in the index, if any. Defaults to **NULL**.  
  
 *pKeyArray*  
 A pointer to an array of variants. The array size corresponds to the number of fields in the index.  
  
 *nKeys*  
 An integer corresponding to the size of the array, which is the number of fields in the index.  
  
> [!NOTE]
>  Do not specify wildcards in the keys. Wildcards will cause `Seek` to return no matching records.  
  
### Return Value  
 Nonzero if matching records are found, otherwise 0.  
  
### Remarks  
 Use the second (array) version of `Seek` to handle indexes of four fields or more.  
  
 `Seek` enables high-performance index searching on table-type recordsets. You must set the current index by calling `SetCurrentIndex` before calling `Seek`. If the index identifies a nonunique key field or fields, `Seek` locates the first record that satisfies the criteria. If you do not set an index, an exception is thrown.  
  
 Note that if you are not creating a UNICODE recordset, the `COleVariant` objects must be explicitly declared ANSI. This can be done by using the [COleVariant::COleVariant](../Topic/COleVariant%20Class.md#colevariant__colevariant)**(** `lpszSrc`**,** `vtSrc` **)** form of constructor with `vtSrc` set to `VT_BSTRT` (ANSI) or by using the **COleVariant** function [SetString](../Topic/COleVariant%20Class.md#colevariant__setstring)**(** `lpszSrc`**,** `vtSrc` **)** with `vtSrc` set to `VT_BSTRT`.  
  
 When you call `Seek`, you pass one or more key values and a comparison operator ("<", "<=", "=", ">=", or ">"). `Seek` searches through the specified key fields and locates the first record that satisfies the criteria specified by `lpszComparison` and `pKey1`. Once found, `Seek` returns nonzero, and makes that record current. If `Seek` fails to locate a match, `Seek` returns zero, and the current record is undefined. When using DAO directly, you must explicitly check the NoMatch property.  
  
 If `lpszComparison` is "=", ">=", or ">", `Seek` starts at the beginning of the index. If `lpszComparison` is "<" or "<=", `Seek` starts at the end of the index and searches backward unless there are duplicate index entries at the end. In this case, `Seek` starts at an arbitrary entry among the duplicate index entries at the end of the index.  
  
 There does not have to be a current record when you use `Seek`.  
  
 To locate a record in a dynaset-type or snapshot-type recordset that satisfies a specific condition, use the Find operations. To include all records, not just those that satisfy a specific condition, use the Move operations to move from record to record.  
  
 You cannot call `Seek` on an attached table of any type because attached tables must be opened as dynaset-type or snapshot-type recordsets. However, if you call `CDaoDatabase::Open` to directly open an installable ISAM database, you can call `Seek` on tables in that database, although the performance may be slow.  
  
 For related information, see the topic "Seek Method" in DAO Help.  
  
##  <a name="cdaorecordset__setabsoluteposition"></a>  CDaoRecordset::SetAbsolutePosition  
 Sets the relative record number of a recordset object's current record.  
  

void SetAbsolutePosition(long lPosition);

  
### Parameters  
 *lPosition*  
 Corresponds to the ordinal position of the current record in the recordset.  
  
### Remarks  
 Calling `SetAbsolutePosition` enables you to position the current record pointer to a specific record based on its ordinal position in a dynaset-type or snapshot-type recordset. You can also determine the current record number by calling [GetAbsolutePosition](#cdaorecordset__getabsoluteposition).  
  
> [!NOTE]
>  This member function is valid only for dynaset-type and snapshot-type recordsets.  
  
 The AbsolutePosition property value of the underlying DAO object is zero-based; a setting of 0 refers to the first record in the recordset. Setting a value greater than the number of populated records causes MFC to throw an exception. You can determine the number of populated records in the recordset by calling the `GetRecordCount` member function.  
  
 If the current record is deleted, the AbsolutePosition property value is not defined, and MFC throws an exception if it is referenced. New records are added to the end of the sequence.  
  
> [!NOTE]
>  This property is not intended to be used as a surrogate record number. Bookmarks are still the recommended way of retaining and returning to a given position and are the only way to position the current record across all types of recordset objects that support bookmarks. In particular, the position of a given record changes when record(s) preceding it are deleted. There is also no assurance that a given record will have the same absolute position if the recordset is re-created again because the order of individual records within a recordset is not guaranteed unless it is created with a SQL statement using an **ORDERBY** clause.  
  
 For related information, see the topic "AbsolutePosition Property" in DAO Help.  
  
##  <a name="cdaorecordset__setbookmark"></a>  CDaoRecordset::SetBookmark  
 Call this member function to position the recordset on the record containing the specified bookmark.  
  

void SetBookmark(COleVariant varBookmark);

  
### Parameters  
 `varBookmark`  
 A [COleVariant](../Topic/COleVariant%20Class.md) object containing the bookmark value for a specific record.  
  
### Remarks  
 When a recordset object is created or opened, each of its records already has a unique bookmark. You can retrieve the bookmark for the current record by calling `GetBookmark` and saving the value to a `COleVariant` object. You can later return to that record by calling `SetBookmark` using the saved bookmark value.  
  
> [!NOTE]
>  Calling [Requery](#cdaorecordset__requery) changes DAO bookmarks.  
  
 Note that if you are not creating a UNICODE recordset, the `COleVariant` object must be explicitly declared ANSI. This can be done by using the [COleVariant::COleVariant](../Topic/COleVariant%20Class.md#colevariant__colevariant)**(** `lpszSrc`**,** `vtSrc` **)** form of constructor with `vtSrc` set to `VT_BSTRT` (ANSI) or by using the **COleVariant** function [SetString](../Topic/COleVariant%20Class.md#colevariant__setstring)**(** `lpszSrc`**,** `vtSrc` **)** with `vtSrc` set to `VT_BSTRT`.  
  
 For related information, see the topics "Bookmark Property" and Bookmarkable Property" in DAO Help.  
  
##  <a name="cdaorecordset__setcachesize"></a>  CDaoRecordset::SetCacheSize  
 Call this member function to set the number of records to be cached.  
  

void SetCacheSize(long lSize);

  
### Parameters  
 `lSize`  
 Specifies the number of records. A typical value is 100. A setting of 0 turns off caching. The setting must be between 5 and 1200 records. The cache may use a considerable amount of memory.  
  
### Remarks  
 A cache is a space in local memory that holds the data most recently retrieved from the server in the event that the data will be requested again while the application is running. Data caching improves the performance of an application that retrieves data from a remote server through dynaset-type recordset objects. When data is requested, the Microsoft Jet database engine checks the cache for the requested data first rather than retrieving it from the server, which takes more time. Data that does not come from an ODBC data source is not saved in the cache.  
  
 Any ODBC data source, such as an attached table, can have a local cache. To create the cache, open a recordset object from the remote data source, call the `SetCacheSize` and `SetCacheStart` member functions, and then call the `FillCache` member function or step through the records by using one of the Move operations. The `lSize` parameter of the `SetCacheSize` member function can be based on the number of records your application can work with at one time. For example, if you are using a recordset as the source of the data to be displayed on screen, you could pass the `SetCacheSize``lSize` parameter as 20 to display 20 records at one time.  
  
 For related information, see the topic "CacheSize, CacheStart Properties" in DAO Help.  
  
##  <a name="cdaorecordset__setcachestart"></a>  CDaoRecordset::SetCacheStart  
 Call this member function to specify the bookmark of the first record in the recordset to be cached.  
  

void SetCacheStart(COleVariant varBookmark);

  
### Parameters  
 `varBookmark`  
 A [COleVariant](../Topic/COleVariant%20Class.md) that specifies the bookmark of the first record in the recordset to be cached.  
  
### Remarks  
 You can use the bookmark value of any record for the `varBookmark` parameter of the `SetCacheStart` member function. Make the record you want to start the cache with the current record, establish a bookmark for that record using [SetBookmark](#cdaorecordset__setbookmark), and pass the bookmark value as the parameter for the `SetCacheStart` member function.  
  
 The Microsoft Jet database engine requests records within the cache range from the cache, and it requests records outside the cache range from the server.  
  
 Records retrieved from the cache do not reflect changes made concurrently to the source data by other users.  
  
 To force an update of all the cached data, pass the `lSize` parameter of `SetCacheSize` as 0, call `SetCacheSize` again with the size of the cache you originally requested, and then call the `FillCache` member function.  
  
 Note that if you are not creating a UNICODE recordset, the `COleVariant` object must be explicitly declared ANSI. This can be done by using the [COleVariant::COleVariant](../Topic/COleVariant%20Class.md#colevariant__colevariant)**(** `lpszSrc`**,** `vtSrc` **)** form of constructor with `vtSrc` set to `VT_BSTRT` (ANSI) or by using the **COleVariant** function [SetString](../Topic/COleVariant%20Class.md#colevariant__setstring)**(** `lpszSrc`**,** `vtSrc` **)** with `vtSrc` set to `VT_BSTRT`.  
  
 For related information, see the topic CacheSize, CacheStart Properties" in DAO Help.  
  
##  <a name="cdaorecordset__setcurrentindex"></a>  CDaoRecordset::SetCurrentIndex  
 Call this member function to set an index on a table-type recordset.  
  

void SetCurrentIndex(LPCTSTR lpszIndex);

  
### Parameters  
 `lpszIndex`  
 A pointer containing the name of the index to be set.  
  
### Remarks  
 Records in base tables are not stored in any particular order. Setting an index changes the order of records returned from the database, but it does not affect the order in which the records are stored. The specified index must already be defined. If you try to use an index object that does not exist, or if the index is not set when you call [Seek](#cdaorecordset__seek), MFC throws an exception.  
  
 You can create a new index for the table by calling [CDaoTableDef::CreateIndex](../Topic/CDaoTableDef%20Class.md#cdaotabledef__createindex) and appending the new index to the Indexes collection of the underlying tabledef by calling [CDaoTableDef::Append](../Topic/CDaoTableDef%20Class.md#cdaotabledef__append), and then reopening the recordset.  
  
 Records returned from a table-type recordset can be ordered only by the indexes defined for the underlying tabledef. To sort records in some other order, you can open a dynaset-type or snapshot-type recordset using a SQL **ORDERBY** clause stored in [CDaoRecordset::m_strSort](#cdaorecordset__m_strsort).  
  
 For related information, see the topic "Index Object" and the definition "current index" in DAO Help.  
  
##  <a name="cdaorecordset__setfielddirty"></a>  CDaoRecordset::SetFieldDirty  
 Call this member function to flag a field data member of the recordset as changed or as unchanged.  
  

void SetFieldDirty( void* pv,
BOOL bDirty = TRUE);

  
### Parameters  
 `pv`  
 Contains the address of a field data member in the recordset or **NULL**. If **NULL**, all field data members in the recordset are flagged. (C++ **NULL** is not the same as Null in database terminology, which means "having no value.")  
  
 `bDirty`  
 **TRUE** if the field data member is to be flagged as "dirty" (changed). Otherwise **FALSE** if the field data member is to be flagged as "clean" (unchanged).  
  
### Remarks  
 Marking fields as unchanged ensures the field is not updated.  
  
 The framework marks changed field data members to ensure they will be written to the record on the data source by the DAO record field exchange (DFX) mechanism. Changing the value of a field generally sets the field dirty automatically, so you will seldom need to call `SetFieldDirty` yourself, but you might sometimes want to ensure that columns will be explicitly updated or inserted regardless of what value is in the field data member. The DFX mechanism also employs the use of **PSEUDONULL**. For more information, see [CDaoFieldExchange::m_nOperation](../Topic/CDaoFieldExchange%20Class.md#cdaofieldexchange__m_noperation).  
  
 If the double-buffering mechanism is not being used, then changing the value of the field does not automatically set the field as dirty. In this case, it will be necessary to explicitly set the field as dirty. The flag contained in [m_bCheckCacheForDirtyFields](#cdaorecordset__m_bcheckcachefordirtyfields) controls this automatic field checking.  
  
> [!NOTE]
>  Call this member function only after you have called [Edit](#cdaorecordset__edit) or [AddNew](#cdaorecordset__addnew).  
  
 Using **NULL** for the first argument of the function will apply the function to all **outputColumn** fields, not **param** fields in `CDaoFieldExchange`. For instance, the call  
  
 [!CODE [NVC_MFCDatabase#6](../CodeSnippet/VS_Snippets_Cpp/NVC_MFCDatabase#6)]  
  
 will set only **outputColumn** fields to **NULL**; **param** fields will be unaffected.  
  
 To work on a **param**, you must supply the actual address of the individual **param** you want to work on, such as:  
  
 [!CODE [NVC_MFCDatabase#7](../CodeSnippet/VS_Snippets_Cpp/NVC_MFCDatabase#7)]  
  
 This means you cannot set all **param** fields to **NULL**, as you can with **outputColumn** fields.  
  
 `SetFieldDirty` is implemented through `DoFieldExchange`.  
  
##  <a name="cdaorecordset__setfieldnull"></a>  CDaoRecordset::SetFieldNull  
 Call this member function to flag a field data member of the recordset as Null (specifically having no value) or as non-Null.  
  

void SetFieldNull( void* pv,
BOOL bNull = TRUE);

  
### Parameters  
 `pv`  
 Contains the address of a field data member in the recordset or **NULL**. If **NULL**, all field data members in the recordset are flagged. (C++ **NULL** is not the same as Null in database terminology, which means "having no value.")  
  
 `bNull`  
 Nonzero if the field data member is to be flagged as having no value (Null). Otherwise 0 if the field data member is to be flagged as non-Null.  
  
### Remarks  
 `SetFieldNull` is used for fields bound in the `DoFieldExchange` mechanism.  
  
 When you add a new record to a recordset, all field data members are initially set to a Null value and flagged as "dirty" (changed). When you retrieve a record from a data source, its columns either already have values or are Null. If it is not appropriate to make a field Null, a [CDaoException](../Topic/CDaoException%20Class.md) is thrown.  
  
 If you are using the double-buffering mechanism, for example, if you specifically wish to designate a field of the current record as not having a value, call `SetFieldNull` with `bNull` set to **TRUE** to flag it as Null. If a field was previously marked Null and you now want to give it a value, simply set its new value. You do not have to remove the Null flag with `SetFieldNull`. To determine whether the field is allowed to be Null, call [IsFieldNullable](#cdaorecordset__isfieldnullable).  
  
 If you are not using the double-buffering mechanism, then changing the value of the field does not automatically set the field as dirty and non-Null. You must specifically set the fields dirty and non-Null. The flag contained in [m_bCheckCacheForDirtyFields](#cdaorecordset__m_bcheckcachefordirtyfields) controls this automatic field checking.  
  
 The DFX mechanism employs the use of **PSEUDONULL**. For more information, see [CDaoFieldExchange::m_nOperation](../Topic/CDaoFieldExchange%20Class.md#cdaofieldexchange__m_noperation).  
  
> [!NOTE]
>  Call this member function only after you have called [Edit](#cdaorecordset__edit) or [AddNew](#cdaorecordset__addnew).  
  
 Using **NULL** for the first argument of the function will apply the function only to **outputColumn** fields, not **param** fields in `CDaoFieldExchange`. For instance, the call  
  
 [!CODE [NVC_MFCDatabase#8](../CodeSnippet/VS_Snippets_Cpp/NVC_MFCDatabase#8)]  
  
 will set only **outputColumn** fields to **NULL**; **param** fields will be unaffected.  
  
##  <a name="cdaorecordset__setfieldvalue"></a>  CDaoRecordset::SetFieldValue  
 Call this member function to set the value of a field, either by ordinal position or by changing the value of the string.  
  

virtual void SetFieldValue( LPCTSTR lpszName,
const COleVariant& varValue);

virtual void SetFieldValue( int nIndex,
const COleVariant& varValue);

void SetFieldValue( LPCTSTR lpszName,
LPCTSTR lpszValue);

void SetFieldValue( int nIndex,
LPCTSTR lpszValue);

  
### Parameters  
 `lpszName`  
 A pointer to a string containing the name of a field.  
  
 `varValue`  
 A reference to a [COleVariant](../Topic/COleVariant%20Class.md) object containing the value of the field's contents.  
  
 `nIndex`  
 An integer that represents the ordinal position of the field in the recordset's Fields collection (zero-based).  
  
 `lpszValue`  
 A pointer to a string containing the value of the field's contents.  
  
### Remarks  
 Use `SetFieldValue` and [GetFieldValue](#cdaorecordset__getfieldvalue) to dynamically bind fields at run time rather than statically binding columns using the [DoFieldExchange](#cdaorecordset__dofieldexchange) mechanism.  
  
 Note that if you are not creating a UNICODE recordset, you must either use a form of `SetFieldValue` that does not contain a `COleVariant` parameter, or the `COleVariant` object must be explicitly declared ANSI. This can be done by using the [COleVariant::COleVariant](../Topic/COleVariant%20Class.md#colevariant__colevariant)**(** `lpszSrc`**,** `vtSrc` **)** form of constructor with `vtSrc` set to `VT_BSTRT` (ANSI) or by using the **COleVariant** function [SetString](../Topic/COleVariant%20Class.md#colevariant__setstring)**(** `lpszSrc`**,** `vtSrc` **)** with `vtSrc` set to `VT_BSTRT`.  
  
 For related information, see the topics "Field Object" and "Value Property" in DAO Help.  
  
##  <a name="cdaorecordset__setfieldvaluenull"></a>  CDaoRecordset::SetFieldValueNull  
 Call this member function to set the field to a Null value.  
  

void SetFieldValueNull(int nIndex);
void SetFieldValueNull(LPCTSTR lpszName); ```

Parameters

nIndex
The index of the field in the recordset, for lookup by zero-based index.

lpszName
The name of the field in the recordset, for lookup by name.

Remarks

C++ NULL is not the same as Null, which, in database terminology, means "having no value."

For related information, see the topics "Field Object" and "Value Property" in DAO Help.

CDaoRecordset::SetLockingMode

Call this member function to set the type of locking for the recordset.

void SetLockingMode(BOOL bPessimistic);

Parameters

bPessimistic
A flag that indicates the type of locking.

Remarks

When pessimistic locking is in effect, the 2K page containing the record you are editing is locked as soon as you call the Edit member function. The page is unlocked when you call the Update or Close member function or any of the Move or Find operations.

When optimistic locking is in effect, the 2K page containing the record is locked only while the record is being updated with the Update member function.

If a page is locked, no other user can edit records on the same page. If you call SetLockingMode and pass a nonzero value and another user already has the page locked, an exception is thrown when you call Edit. Other users can read data from locked pages.

If you call SetLockingMode with a zero value and later call Update while the page is locked by another user, an exception occurs. To see the changes made to your record by another user (and lose your changes), call the SetBookmark member function with the bookmark value of the current record.

When working with ODBC data sources, the locking mode is always optimistic.

CDaoRecordset::SetParamValue

Call this member function to set the value of a parameter in the recordset at run time.

virtual void SetParamValue(
    int nIndex,  
    const COleVariant& varValue);

 
virtual void SetParamValue(
    LPCTSTR lpszName,  
    const COleVariant& varValue);

Parameters

nIndex
The numerical position of the parameter in the querydef's Parameters collection.

var
The value to set; see Remarks.

lpszName
The name of the parameter whose value you want to set.

Remarks

The parameter must already have been established as part of the recordset's SQL string. You can access the parameter either by name or by its index position in the collection.

Specify the value to set as a COleVariant object. For information about setting the desired value and type in your COleVariant object, see class COleVariant. Note that if you are not creating a UNICODE recordset, the COleVariant object must be explicitly declared ANSI. This can be done by using the COleVariant::COleVariant( lpszSrc, vtSrc ) form of constructor with vtSrc set to VT_BSTRT (ANSI) or by using the COleVariant function SetString( lpszSrc, vtSrc ) with vtSrc set to VT_BSTRT.

CDaoRecordset::SetParamValueNull

Call this member function to set the parameter to a Null value.

void SetParamValueNull(int nIndex);  
void SetParamValueNull(LPCTSTR lpszName);
```  
  
### Parameters  
 `nIndex`  
 The index of the field in the recordset, for lookup by zero-based index.  
  
 `lpszName`  
 The name of the field in the recordset, for lookup by name.  
  
### Remarks  
 C++ **NULL** is not the same as Null, which, in database terminology, means "having no value."  
  
##  <a name="cdaorecordset__setpercentposition"></a>  CDaoRecordset::SetPercentPosition  
 Call this member function to set a value that changes the approximate location of the current record in the recordset object based on a percentage of the records in the recordset.  
  

void SetPercentPosition(float fPosition);

  
### Parameters  
 *fPosition*  
 A number between 0 and 100.  
  
### Remarks  
 When working with a dynaset-type or snapshot-type recordset, first populate the recordset by moving to the last record before you call `SetPercentPosition`. If you call `SetPercentPosition` before fully populating the recordset, the amount of movement is relative to the number of records accessed as indicated by the value of [GetRecordCount](#cdaorecordset__getrecordcount). You can move to the last record by calling `MoveLast`.  
  
 Once you call `SetPercentPosition`, the record at the approximate position corresponding to that value becomes current.  
  
> [!NOTE]
>  Calling `SetPercentPosition` to move the current record to a specific record in a recordset is not recommended. Call the [SetBookmark](#cdaorecordset__setbookmark) member function instead.  
  
 For related information, see the topic "PercentPosition Property" in DAO Help.  
  
##  <a name="cdaorecordset__update"></a>  CDaoRecordset::Update  
 Call this member function after a call to the `AddNew` or **Edit** member function.  
  

virtual void Update();

  
### Remarks  
 This call is required to complete the `AddNew` or **Edit** operation.  
  
 Both `AddNew` and **Edit** prepare an edit buffer in which the added or edited data is placed for saving to the data source. **Update** saves the data. Only those fields marked or detected as changed are updated.  
  
 If the data source supports transactions, you can make the **Update** call (and its corresponding `AddNew` or **Edit** call) part of a transaction.  
  
> [!CAUTION]
>  If you call **Update** without first calling either `AddNew` or **Edit**, **Update** throws a `CDaoException`. If you call `AddNew` or **Edit**, you must call **Update** before you call [MoveNext](#cdaorecordset__movenext) or close either the recordset or the data source connection. Otherwise, your changes are lost without notification.  
  
 When the recordset object is pessimistically locked in a multiuser environment, the record remains locked from the time **Edit** is used until the updating is complete. If the recordset is optimistically locked, the record is locked and compared with the pre-edited record just before it is updated in the database. If the record has changed since you called **Edit**, the **Update** operation fails and MFC throws an exception. You can change the locking mode with `SetLockingMode`.  
  
> [!NOTE]
>  Optimistic locking is always used on external database formats, such as ODBC and installable ISAM.  
  
 For related information, see the topics "AddNew Method", "CancelUpdate Method", "Delete Method", "LastModified Property", "Update Method", and "EditMode Property" in DAO Help.  
  
## See Also  
 [CObject Class](../Topic/CObject%20Class.md)   
 [Hierarchy Chart](../Topic/Hierarchy%20Chart.md)   
 [CDaoTableDef Class](../Topic/CDaoTableDef%20Class.md)   
 [CDaoWorkspace Class](../Topic/CDaoWorkspace%20Class.md)   
 [CDaoDatabase Class](../Topic/CDaoDatabase%20Class.md)   
 [CDaoQueryDef Class](../Topic/CDaoQueryDef%20Class.md)