Я пытаюсь вставить файл в базу данных MS Access, в поле OLE Object
тип. я использую C++
а также ADO
,
В настоящее время я получаю ошибку Invalid pointer error
,
Я думаю, что моя проблема в неправильном обращении с вариантами, так как я использую их впервые. Я учусь у этот пример кода но есть проблемы с пониманием, как вставить файл с диска в variant
,
Они читают его из базы данных и копируют в новую запись, поэтому часть, где я читаю файл с диска, а затем вставляю его в вариант, отсутствует.
Я запускаю свой код в графическом интерфейсе, когда выбран пункт меню. База данных имеет одну таблицу с именем test
с полями ID
который является первичным ключом и field
который из OLE 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);
}
Можете ли вы помочь мне изменить этот фрагмент кода, чтобы я мог вставить файл в вариант?
Я искал здесь помощь и два сообщения, которые дали мне идею. Все еще ни одно из моих решений не работает. Вы можете увидеть их в приведенном выше фрагменте кода, в комментариях.
Теперь я получаю следующую ошибку: a problem occurred while microsoft access was communicating with the ole server or activex control
в MS Access. Я искал в Интернете решение, но мне не повезло, каждая ссылка утверждает, что это связано с доступом, а не с кодом.
Пожалуйста помоги…
Поскольку вы уже используете ADODB.Connection
а также ADODB.Recordset
объекты, которые вы должны быть в состоянии использовать двоичный ADODB.Stream
объект для управления содержимым файла с
.LoadFromFile
заполнить поток содержимым файла, и.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