c++ - 使用 ADO 将原始文件数据插入 BLOB ("OLE Object") 访问表的字段

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

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

目前我得到错误无效指针错误

我认为我的问题是对变体的处理不当,因为这是我第一次使用它们。我在学习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);
    }

你能帮我修改这个代码片段,这样我就可以将文件插入到变体中吗?

编辑:

我在这里搜索了帮助和两个给了我想法的帖子。我的解决方案仍然无效。您可以在上面的代码片段中的评论中看到它们。

我现在得到的是以下错误:Microsoft Access 与 MS Access 中的 ole 服务器或 activex 控件通信时出现问题。我在网上搜索了解决方案,但没有成功,每个链接都声称它与访问权限有关,与代码无关。

请帮忙...

最佳答案

因为您已经在使用 ADODB.ConnectionADODB.Recordset 对象,您应该能够使用二进制 ADODB.Stream 对象来操作文件内容

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

很遗憾,我无法提供 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

关于c++ - 使用 ADO 将原始文件数据插入 BLOB ("OLE Object") 访问表的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27234746/

相关文章:

c++ - 即使函数存在,也出现 undefined reference 错误

c++ - 无法取消引用插入到 vector 中的类对象指针

C++ 检查日期是否有效

sql-server - 使用 Datasnap 构建真正的数据库应用程序

vba - 从 Excel VBA 到 PostgreSQL 数据库的连接缓慢

c++ - 如何在编译时检查类型是否为多态

sql-server - 将参数传递给 TADOStoredProc 的更好方法 (Delphi)

windows - 查找所有可用的 OLE 容器

c++ - 如何提取 OLE 容器的内容?

c - 如何通过 COM 接口(interface)以编程方式激活 OLE 控件?