Field Status Data Members in Wizard-Generated Accessors

The ATL OLE DB Consumer wizard is not available in Visual Studio 2019 and later. You can still add the functionality manually. For more information, see Creating a Consumer Without Using a Wizard.

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:

class CAuthorsAccessor
{
public:
   LONG m_AuID;
   TCHAR m_Author[53];
   LONG m_YearBorn;

   DBSTATUS m_dwAuIDStatus;
   DBSTATUS m_dwAuthorStatus;
   DBSTATUS m_dwYearBornStatus;

   DBLENGTH m_dwAuIDLength;
   DBLENGTH m_dwAuthorLength;
   DBLENGTH m_dwYearBornLength;

   DEFINE_COMMAND_EX(CAuthorsAccessor, L" \
   SELECT \
      AuID, \
      Author, \
      YearBorn \
      FROM dbo.Authors")

   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()
...

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:

    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()
    };
    
  • Then, access the length and/or status as shown:

    CTable<CAccessor<CProducts >> product;
    CSession session;
    
    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", product.szName, product.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.

See also

Working with OLE DB Consumer Templates