使用ADO将原始文件数据插入到Access表的BLOB(“OLE Object”)字段中 [英] Insert raw file data into BLOB ("OLE Object") field of Access table using ADO

查看:1122
本文介绍了使用ADO将原始文件数据插入到Access表的BLOB(“OLE Object”)字段中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图插入一个文件到MS Access数据库,到 OLE对象类型的字段。我使用 C ++ ADO



目前我收到错误无效的指针错误



我认为我的问题是错误的变体,因为这是我第一次使用它们。我从此代码示例中学习,但是有解决如何从磁盘插入文件到 variant 有问题。



他们从数据库读取,并将其复制到新记录中,因此我从磁盘读取文件,然后将其插入变体的部分缺失。



当我选择菜单项时,我在GUI中激活我的代码。数据库有一个名为 test 的表,其中的字段 ID 是主键和字段这是 OLE对象类型。



在线搜索后,我发现没有什么可以帮助我



以下是说明问题的最小代码段(错误检查极少):

  wchar_t * bstrConnect = LProvider = Microsoft.ACE.OLEDB.12.0; \ 
数据源= C:\\Users\\Smiljkovic85\\Desktop\\ \\\OLE.accdb;

try
{
HRESULT hr = CoInitialize(NULL);

//连接
ADODB :: _ ConnectionPtr pConn(LADODB.Connection);

// recordset
ADODB :: _ RecordsetPtr pRS(LADODB.Recordset);

//连接到DB
hr = pConn->打开(bstrConnect,Ladmin,L,ADODB :: adConnectUnspecified);

//打开文件
std :: ifstream(LC:\\Users\\Smiljkovic85\\Desktop\\file.pdf,
std :: ios :: ate | std :: ios :: binary);

//获取文件大小
int fileSize = in.tellg();

//这里我尝试修改上面链接的示例代码
pRS-> Open(Ltest,_variant_t((IDispatch *)pConn,true),
ADODB :: adOpenKeyset,ADODB :: adLockOptimistic,ADODB :: adCmdTable);

//添加新记录
pRS-> AddNew();

//复制粘贴
_variant_t varChunk;

SAFEARRAY FAR * psa;
SAFEARRAYBOUND rgsabound [1];
rgsabound [0] .lLbound = 0;
//修改为我们的文件大小
rgsabound [0] .cElements = fileSize;
psa = SafeArrayCreate(VT_UI1,1,rgsabound);

// ===================尝试将文件添加到变量
char * chData =(char *)psa-> ; pvData;

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

/ * =============我甚至尝试了以下操作:

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

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

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

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

//将Safe数组分配给变体。
varChunk.vt = VT_ARRAY | VT_UI1;
varChunk.parray = psa;

pRS-> Fields-> GetItem(Lfield) - > AppendChunk(varChunk);
//将此记录添加到DB
pRS-> Update();

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

您能帮我修改这段代码, ?



编辑:



我在这里搜索帮助和两个帖子给了我一个想法。仍然没有我的解决方案工作。



我现在得到的是以下错误:当微软发生问题时访问正在与MS Access中的ole服务器或activex控制进行通信。我已经在线搜索解决方案,但没有运气,每个链接声称它与访问,而不是与代码。



请帮助...

解决方案

由于您已经使用 ADODB.Connection ADODB .Recordset 对象,您应该能够使用二进制 ADODB.Stream 对象来操作文件内容




  • .LoadFromFile 以填充Stream的文件内容,

  • .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
设置rst =新ADODB.Recordset
rst.Opentest,con,adOpenKeyset,adLockOptimistic ,adCmdTable
设置strm =新ADODB.Stream
strm.Type = adTypeBinary
strm.Open
strm.LoadFromFileC:\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
设置con = Nothing
strm.Close
设置strm = Nothing


I am trying to insert a file into MS Access database, into a field of OLE Object type. I am using C++ and ADO.

Currently I get error Invalid pointer error.

I think that my problem is mishandling variants since this is the first time I use them. I am learning from this code example but have problem understanding how to insert file from disk into variant.

They read it from database, and copied it into new record so the part where I read file from disk and then insert it into variant is missing.

I am firing off my code in GUI when menu item is selected. Database has one table named test with fields ID which is primary key and field which is of OLE Object type.

After searching online I have found nothing that can help me.

Here is smallest code snippet possible that illustrates the problem ( error checking is minimal):

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);
    }

Can you help me to modify this code snippet so I can insert file into variant?

EDIT:

I have searched here for help and two posts that gave me an idea. Still none of my solutions work. You can see them in the above code snippet, in the comments.

What I get now, is the following error: a problem occurred while microsoft access was communicating with the ole server or activex control in MS Access. I have searched online for solution but had no luck, every link claims it has to do with access and not with the code.

Please help...

解决方案

Since you are already using ADODB.Connection and ADODB.Recordset objects you should be able to use a binary ADODB.Stream object to manipulate the file contents with

  • .LoadFromFile to fill the Stream with the file contents, and
  • .Read to pull it back out of the Stream and store it in the database field.

Unfortunately I cannot offer a C++ example, but in VBA the code would be:

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

这篇关于使用ADO将原始文件数据插入到Access表的BLOB(“OLE Object”)字段中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆