OLE DB 大容量复制操作始终将 True 加载到位列中

OLE DB Bulk Copy Operation Always Loads True into Bit Columns

我正在对 SQL 服务器数据库使用 OLE DB 批量复制操作,但是我在将数据加载到 bit 列时遇到问题 - 它们总是填充有 true!

我创建了一个 simple reproduction program from Microsoft's sample code with the snippet that I adjusted below. My program includes a little SQL script to create the destination table. I had to download and install the x64 version of the SQL Server OLE DB driver 来构建它。

// Set up custom bindings.  
    oneBinding.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
    oneBinding.iOrdinal = 1;
    oneBinding.pTypeInfo = NULL;
    oneBinding.obValue = ulOffset + offsetof(COLUMNDATA, bData);
    oneBinding.obLength = ulOffset + offsetof(COLUMNDATA, dwLength);
    oneBinding.obStatus = ulOffset + offsetof(COLUMNDATA, dwStatus);
    oneBinding.cbMaxLen = 1;   // Size of varchar column.  
    oneBinding.pTypeInfo = NULL;
    oneBinding.pObject = NULL;
    oneBinding.pBindExt = NULL;
    oneBinding.dwFlags = 0;
    oneBinding.eParamIO = DBPARAMIO_NOTPARAM;
    oneBinding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
    oneBinding.bPrecision = 0;
    oneBinding.bScale = 0;
    oneBinding.wType = DBTYPE_BOOL;
    ulOffset = oneBinding.cbMaxLen + offsetof(COLUMNDATA, bData);
    ulOffset = ROUND_UP(ulOffset, COLUMN_ALIGNVAL);

    if (FAILED(hr =
        pIFastLoad->QueryInterface(IID_IAccessor, (void**)&pIAccessor)))
        return hr;

    if (FAILED(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
        1,
        &oneBinding,
        ulOffset,
        &hAccessor,
        &oneStatus)))
        return hr;

    // Set up memory buffer.  
    pData = new BYTE[40];
    if (!(pData /* = new BYTE[40]*/)) {
        hr = E_FAIL;
        goto cleanup;
    }

    pcolData = (COLUMNDATA*)pData;
    pcolData->dwLength = 1;
    pcolData->dwStatus = 0;

    for (i = 0; i < 10; i++)
    {
        if (i % 2 == 0)
        {
            pcolData->bData[0] = 0x00;
        }
        else
        {
            pcolData->bData[0] = 0xFF;
        }


        if (FAILED(hr = pIFastLoad->InsertRow(hAccessor, pData)))
            goto cleanup;
    }

很可能是我将错误的值放入缓冲区,或者其他一些常量值不正确。我确实发现 an article 描述了各种数据类型转换的安全性,它看起来像 byte to bool 是安全的......但是如果它只是一个字节数组,缓冲区如何知道我要放入其中的数据类型?

弄明白了,我没有正确地将演示从加载字符串切换到固定宽度值。对于字符串,数据 blob 获取指向该值的宽度为 1 的指针,而固定宽度的值获取实际数据。

所以我的 COLUMNDATA 结构现在看起来像这样:

// How to lay out each column in memory.  
struct COLUMNDATA {
    DBLENGTH dwLength;   // Length of data (not space allocated).  
    DWORD dwStatus;   // Status of column.  
    VARIANT_BOOL bData; // Value, or if a string, a pointer to the value.
};

相关长度固定在这里:

pcolData = (COLUMNDATA*)pData;
pcolData->dwLength = sizeof(VARIANT_BOOL); // using a short.. make it two
pcolData->dwStatus = DBSTATUS_S_OK; // Indicates that the data value is to be used, not null

循环的小值设置如下所示:

for (i = 0; i < 10; i++)
{
    if (i % 2 == 0)
    {
        pcolData->bData = VARIANT_TRUE;
    }
    else
    {
        pcolData->bData = VARIANT_FALSE;
    }

    if (FAILED(hr = pIFastLoad->InsertRow(hAccessor, pData)))
        goto cleanup;
}

我已经为 obValue 属性 更新了 repository with the working code. I was inspired to make this change after reading the documentation