Search code examples
c++sql-serveroledb

How to tell a column is text or ntext when connecting to database using CDynamicAccessor?


I'm having a C++ application connecting to the MS SQL Server 2005 using CDynamicAccessor. When my column is text or ntext, the CDynamicAccessor::GetColumnType always return DBTYPE_IUNKNOWN. I can bind the data as ISequentialStream and read the byte stream out. However, how can I tell if the column that I'm reading is text or ntext, and hence, to interpret the byte stream as ASCII or Unicode?


Solution

  • The CDynamicAccessor class overwrites the original DBTYPE value of the column with DBTYPE_UNKNOWN. In order to get the original DBTYPE, we need to call the GetColumnInfo function. An example of how to do this is the DynamicConsumer sample application included in the Visual Studio 2008 samples:

    // the following case will handle BLOBs binded as ISequentialStream/IStream pointer
    if( dbtype == DBTYPE_IUNKNOWN )
    {
        // first we have to determine what was the column's type originally reported by the provider
        CComHeapPtr<DBCOLUMNINFO> spColumnInfo;
        CComHeapPtr<OLECHAR> spStringsBuffer;
        DBORDINAL nColumns = 0;
        HRESULT hres = rs.CDynamicAccessor::GetColumnInfo( rs.m_spRowset, &nColumns, &spColumnInfo, &spStringsBuffer );
        ATLASSERT( SUCCEEDED( hres ) );
        ATLASSERT( col <= nColumns );
        DBTYPE wType = spColumnInfo[col-1].wType;
        ...
    }
    

    The alternative solution is to set the CDynamicAccessor to DBBLOBHANDLING_NOSTREAMS, which seems to result in much less complicated code to handle data loading (you can see this in the full VS2008 sample code). However, I'm not sure why using stream is the default option, and if there is any disadvantages with using no streams.