使用ADO将原始文件数据插入Access表的BLOB(“OLE对象”)字段

时间:2014-12-01 18:23:46

标签: c++ ado ole ms-access-2013 variant

我正在尝试将文件插入MS Access数据库,进入OLE Object类型的字段。我正在使用C++ADO

目前我收到错误Invalid pointer error

我认为我的问题是错误处理变种,因为这是我第一次使用它们。我正在向this code example学习,但在了解如何将文件从磁盘插入variant时遇到问题。

他们从数据库中读取它,并将其复制到新记录中,以便我从磁盘读取文件然后将其插入变量中的部分丢失。

当选择菜单项时,我在GUI中触发了我的代码。数据库有一个名为test的表,其中字段ID是主键,fieldOLE Object类型。

在线搜索后,我找不到任何可以帮助我的信息。

这是可能的最小代码片段,用于说明问题(错误检查是最小的):

wchar_t *bstrConnect = L"Provider=Microsoft.ACE.OLEDB.12.0; \
        Data Source = C:\\Users\\Smiljkovic85\\Desktop\\OLE.accdb";

    try
    {
        HRESULT hr = CoInitialize(NULL);

        // connection
        ADODB::_ConnectionPtr pConn(L"ADODB.Connection");

        // recordset
        ADODB::_RecordsetPtr pRS(L"ADODB.Recordset");

        // connect to DB
        hr = pConn->Open(bstrConnect, L"admin", L"", ADODB::adConnectUnspecified);

        // open file
        std::ifstream in(L"C:\\Users\\Smiljkovic85\\Desktop\\file.pdf",
               std::ios::ate | std::ios::binary);

        // get file size
        int fileSize = in.tellg();

        // here I tried to adapt code from the example linked above
        pRS->Open(L"test", _variant_t((IDispatch*)pConn, true), 
            ADODB::adOpenKeyset, ADODB::adLockOptimistic, ADODB::adCmdTable);

        // add new record
        pRS->AddNew();

        // copy pasted
        _variant_t varChunk;

        SAFEARRAY FAR *psa;
        SAFEARRAYBOUND rgsabound[1];
        rgsabound[0].lLbound = 0;
        // modify to our file size
        rgsabound[0].cElements = fileSize;
        psa = SafeArrayCreate(VT_UI1, 1, rgsabound);

        //=================== try to add file into variant
        char *chData = (char *)psa->pvData;

        chData = new char[fileSize];
        in.read(chData, fileSize);

        /* ============= I have even tried the following :

        char *chData = new char[fileSize];
        in.read(chData, fileSize);

        BYTE* pData;
        SafeArrayAccessData(psa, (void **)&pData);
        memcpy(pData, chData, fileSize);
        SafeArrayUnaccessData(psa);

        ===============*/

        //=================================================

        // Assign the Safe array  to a variant. 
        varChunk.vt = VT_ARRAY | VT_UI1;
        varChunk.parray = psa;

        pRS->Fields->GetItem(L"field")->AppendChunk(varChunk);
        // add this record into DB
        pRS->Update();

        // cleanup
        delete[] chData;
        in.close();
        pRS->Close();
        pConn->Close();
        CoUninitialize();
    }
    catch (_com_error e)
    {
        MessageBox(hWnd, (LPWSTR)e.Description(), L"", 0);
    }

您能否帮我修改此代码段,以便将文件插入变体?

编辑:

我在这里寻求帮助,两篇帖子给了我一个想法。仍然没有一个解决方案有效。您可以在上面的代码段中的注释中看到它们。

我现在得到的是以下错误:MS Access中的a problem occurred while microsoft access was communicating with the ole server or activex control。我在网上搜索了解决方案,但没有运气,每个链接声称它与访问有关,而不是代码。

请帮忙......

1 个答案:

答案 0 :(得分:2)

由于您已经在使用ADODB.ConnectionADODB.Recordset个对象,因此您应该可以使用二进制ADODB.Stream对象来操作文件内容

  • .LoadFromFile用文件内容填充Stream,
  • .Read将其从流中拉出并将其存储在数据库字段中。

不幸的是我无法提供C ++示例,但在VBA中,代码将是:

Dim con As ADODB.Connection, rst As ADODB.Recordset, strm As ADODB.Stream
Set con = New ADODB.Connection
con.Open _
        "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source=C:\Users\Public\Database1.accdb"
Set rst = New ADODB.Recordset
rst.Open "test", con, adOpenKeyset, adLockOptimistic, adCmdTable
Set strm = New ADODB.Stream
strm.Type = adTypeBinary
strm.Open
strm.LoadFromFile "C:\Users\Gord\Desktop\test.pdf"
rst.AddNew
strm.Position = 0
rst.Fields("FileData").Value = strm.Read
rst.Update
rst.Close
Set rst = Nothing
con.Close
Set con = Nothing
strm.Close
Set strm = Nothing