Field Status Data Members in Wizard-Generated Accessors
When you use the ATL OLE DB Consumer Wizard to create a consumer, the wizard generates a data member in the user record class for each field that you specify in your column map. Each data member is of type DWORD and contains a status value corresponding to its respective field.
For example, for a data member m_OwnerID, the wizard generates an additional data member for field status (dwOwnerIDStatus) and another one for field length (dwOwnerIDLength). It also generates a column map with COLUMN_ENTRY_LENGTH_STATUS entries.
This is shown in the following code:
[db_source("insert connection string")]
[db_command(" \
SELECT \
Au_ID, \
Author, \
`Year Born`, \
FROM Authors")]
class CAuthors
{
public:
// The following wizard-generated data members contain status
// values for the corresponding fields in the column map. You
// can use these values to hold NULL values that the database
// returns or to hold error information when the compiler returns
// errors. See "Field Status Data Members in Wizard-Generated
// Accessors" in the Visual C++ documentation for more information
// on using these fields.
DWORD m_dwAuIDStatus;
DWORD m_dwAuthorStatus;
DWORD m_dwYearBornStatus;
// The following wizard-generated data members contain length
// values for the corresponding fields in the column map.
DWORD m_dwAuIDLength;
DWORD m_dwAuthorLength;
DWORD m_dwYearBornLength;
BEGIN_COLUMN_MAP(CAuthorsAccessor)
COLUMN_ENTRY_LENGTH_STATUS(1, m_AuID, dwAuIDLength, dwAuIDStatus)
COLUMN_ENTRY_LENGTH_STATUS(2, m_Author, dwAuthorLength, dwAuthorStatus)
COLUMN_ENTRY_LENGTH_STATUS(3, m_YearBorn, dwYearBornLength, dwYearBornStatus)
END_COLUMN_MAP()
[ db_column(1, status=m_dwAuIDStatus, length=m_dwAuIDLength) ] LONG m_AuID;
[ db_column(2, status=m_dwAuthorStatus, length=m_dwAuthorLength) ] TCHAR m_Author[51];
[ db_column(3, status=m_dwYearBornStatus, length=m_dwYearBornLength) ] SHORT m_YearBorn;
void GetRowsetProperties(CDBPropSet* pPropSet)
{
pPropSet->AddProperty(DBPROP_IRowsetChange, true);
pPropSet->AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_DELETE);
}
};
Note
If you modify the user record class or write your own consumer, the data variables must come before the status and length variables.
You can use the status values for debugging purposes. If code generated by the ATL OLE DB Consumer Wizard generates compilation errors such as DB_S_ERRORSOCCURRED or DB_E_ERRORSOCCURRED, you should first look at the current values of the field status data members. Those that have nonzero values correspond to the offending columns.
You can also use the status values to set a NULL value for a particular field. Doing so helps you in cases in which you want to distinguish a field value as NULL rather than zero. It is up to you to decide whether NULL is a valid value or a special value and decide how your application should handle it. OLE DB defines DBSTATUS_S_ISNULL as the correct means of specifying a generic NULL value. If the consumer reads data and the value is null, the status field is set to DBSTATUS_S_ISNULL. If the consumer wants to set a NULL value, the consumer sets the status value to DBSTATUS_S_ISNULL before calling the provider.
Next, open Oledb.h and search for DBSTATUSENUM. You can then match the numerical value of the nonzero status against the DBSTATUSENUM enumeration values. If the enumeration name is not sufficient to tell you what is wrong, see the "Status" topic in the "Binding Data Values" section of the OLE DB Programmer's Guide. This topic contains tables of status values used when getting or setting data. For information about length values, see the "Length" topic in the same section.
Retrieving the Length or Status of a Column
You can retrieve the length of a variable-length column or the status of a column (to check for DBSTATUS_S_ISNULL, for example):
To get the length, use the COLUMN_ENTRY_LENGTH macro.
To get the status, use the COLUMN_ENTRY_STATUS macro.
To get both, use COLUMN_ENTRY_LENGTH_STATUS, as shown below.
class CProducts
{
public:
char szName[40];
long nNameLength;
DBSTATUS nNameStatus;
BEGIN_COLUMN_MAP(CProducts)
// Bind the column to CProducts.m_ProductName.
// nOrdinal is zero-based, so the column number of m_ProductName is 1.
COLUMN_ENTRY_LENGTH_STATUS(1, szName, nNameLength, nNameStatus)
END_COLUMN_MAP()
};
CTable<CAccessor<CProducts > > product;
product.Open(session, "Product");
while (product.MoveNext() == S_OK)
{
// Check the product name isn't NULL before tracing it
if (product.nNameStatus == DBSTATUS_S_OK)
ATLTRACE("%s is %d characters\n", szName, nNameLength);
}
When you use CDynamicAccessor, the length and status are bound for you automatically. To retrieve the length and status values, use the GetLength and GetStatus member functions.