ВЪВЕДЕНИЕ И СЪОТВЕТНА ИНФОРМАЦИЯ:
Написах демо приложение в опита си да науча как да използвам ADO
потоци. Всичко работи добре, освен в един специален случай. Позволете ми да започна, като дам подходяща информация:
Използвам WinAPI
за създаване на GUI и зареждам (и го записвам на диска)/вмъквам BLOB при натискане на бутон. Бутоните са в диалогов прозорец.
ПРОБЛЕМ:
Когато натисна бутона за вмъкване на BLOB в базата данни, виждам как се вмъква (държа MS Access отворен). Ако се опитам да заредя съществуващ BLOB от базата данни, нищо не се случва, но не се сигнализират грешки.
Въпреки това, ако извърша вмъкване, след което затворя и отворя отново диалогов прозорец, натискането на бутона за зареждане на BLOB и запазването му на диск работи добре.
Работя с Windows 8.1, използвайки Visual Studio 2013 на лаптоп с двуядрен процесор x64 (това може да е важно да се спомене). Тествах приложението си на дял C:\, където е операционната система, просто реших да спомена, в случай че е подходящо.
РЕДАКТИРАНЕ:
Изпробвах приложението си на дял D и работи. Това означава, че проблемът е някъде в разрешенията. Можете ли да ми помогнете с това, защото нямам представа как да започна да решавам това?
КРАЙ НА РЕДАКТИРАНЕ
SSCCE:
За да ви помогнем още повече, следвайте внимателно инструкциите, за да създадете много минимален примерен код, който възпроизвежда проблема:
1.) Създайте default Win32 project
във Visual Studio.
2.) В stdafx.h
добавете следното точно под #include <windows.h>
:
#include <comutil.h>
#include <stdio.h>
#include <ole2.h>
#include <string>
#include <shlwapi.h>
#pragma comment( lib, "comsuppw.lib")
#pragma comment( lib, "shlwapi.lib")
3.) Добавете следното във вашия основен .cpp
файл точно под #include
директиви:
#import <C:\\Program Files\\Common Files\\System\\ado\\msado15.dll> \
rename( "EOF", "AdoNSEOF" )
4.) добавете следната функция над процедурата на диалоговия прозорец About
:
BOOL OpenFile(HWND hDlg, LPWSTR szFileName, LPWSTR szFilter)
{
// prepare OPENFILE dialog
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDlg;
ofn.lpstrFilter = szFilter;
ofn.lpstrFile = szFileName;
ofn.lpstrFile[0] = L'\0';
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST |
OFN_DONTADDTORECENT | OFN_HIDEREADONLY |
OFN_PATHMUSTEXIST;
ofn.lpstrDefExt = L".pdf";
if (GetOpenFileName(&ofn))
return TRUE;
return FALSE;
}
5.) Заменете диалоговата процедура About
с това:
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
// connection string
static wchar_t bstrConnect[MAX_PATH];
switch (message)
{
case WM_INITDIALOG:
{
// create connection string by choosing database
wchar_t szFile[MAX_PATH];
OpenFile(hDlg, szFile, L".accdb\0");
swprintf_s(bstrConnect, MAX_PATH,
L"Provider=Microsoft.ACE.OLEDB.12.0; Data Source = %s;", szFile);
}
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON1) // save BLOB to database
{
wchar_t szFileName[MAX_PATH] = L"";
if (OpenFile(hDlg, szFileName, L"All files\0*.*"))
{
try
{
HRESULT hr = CoInitialize(NULL);
ADODB::_ConnectionPtr pConn(L"ADODB.Connection");
ADODB::_RecordsetPtr pRS(L"ADODB.Recordset");
hr = pConn->Open(bstrConnect,
L"", L"", ADODB::adConnectUnspecified);
// create new recordset
pRS->Open( L"test", _variant_t((IDispatch*)pConn, true),
ADODB::adOpenKeyset,
ADODB::adLockOptimistic,
ADODB::adCmdTable);
// create stream object
ADODB::_StreamPtr pStream(L"ADODB.Stream");
// set stream type
pStream->Type = ADODB::adTypeBinary;
// missing parameter for Open
_variant_t varOptional(DISP_E_PARAMNOTFOUND, VT_ERROR);
// open stream
pStream->Open(varOptional,
ADODB::adModeUnknown,
ADODB::adOpenStreamUnspecified,
_bstr_t(L""), _bstr_t(L""));
// open selected file
hr = pStream->LoadFromFile(szFileName);
// error checking
if (FAILED(hr))
throw _com_error(hr);
// add new blank record
pRS->AddNew();
// position stream to beginning
pStream->Position = 0;
// insert data to recordset
PathStripPath(szFileName); // leave only filename
pRS->Fields->GetItem(L"tip")->Value = szFileName;
pRS->Fields->GetItem(L"field")->Value =
pStream->Read(ADODB::adReadAll);
// insert data
pRS->Update();
//cleanup
pRS->Close();
pConn->Close();
pStream->Close();
CoUninitialize();
MessageBeep(0);
}
catch (_com_error e)
{
MessageBox(hDlg, (LPWSTR)e.Description(), L"", 0);
}
}
}
if (LOWORD(wParam) == IDC_BUTTON3) // load BLOB and save it into disk
{
try
{
// napravi upit
HRESULT hr = CoInitialize(NULL);
ADODB::_ConnectionPtr pConn(L"ADODB.Connection");
ADODB::_RecordsetPtr pRS(L"ADODB.Recordset");
hr = pConn->Open(bstrConnect, L"", L"", ADODB::adConnectUnspecified);
// create stream object
ADODB::_StreamPtr pStream(L"ADODB.Stream");
// set stream type
pStream->Type = ADODB::adTypeBinary;
// missing parameter for Open
_variant_t varOptional(DISP_E_PARAMNOTFOUND, VT_ERROR);
// open stream
pStream->Open(varOptional,
ADODB::adModeUnknown,
ADODB::adOpenStreamUnspecified,
_bstr_t(L""), _bstr_t(L""));
// primary key is taken from edit control
wchar_t query[200] = L"";
swprintf_s(query, 200, L"select tip, field from test where ID = %d;",
(int)GetDlgItemInt(hDlg, IDC_EDIT1, FALSE, FALSE));
pRS->Open(query, _variant_t((IDispatch *)pConn, true),
ADODB::adOpenUnspecified, ADODB::adLockPessimistic,
ADODB::adCmdText);
if (NULL == pRS)
MessageBox(hDlg, L"Empty recordset!", L"", 0);
hr = pStream->Write(pRS->Fields->GetItem(L"field")->Value);
if (FAILED(hr))
MessageBox(hDlg, L"stream write failed", L"", 0);
// save to file
// store this file on disk
// int he same place our app is running
wchar_t szFileName[MAX_PATH] = L"";
swprintf_s(szFileName, MAX_PATH, L".\\%s",
pRS->Fields->GetItem(L"tip")->Value.bstrVal);
hr = pStream->SaveToFile(szFileName, ADODB::adSaveCreateOverWrite);
if (FAILED(hr))
MessageBox(hDlg, L"save to file failed", L"", 0);
//cleanup
pRS->Close();
pConn->Close();
pStream->Close();
CoUninitialize();
MessageBeep(0);
}
catch (_com_error e)
{
MessageBox(hDlg, (LPWSTR)e.Description(), L"", 0);
}
}
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
7.) Преработете диалоговия прозорец About
в редактора rc
, както е показано по-долу:
- Контролът на завъртане има набор от стилове
auto buddy
,right align, and
set приятелски цели числа - бутоните са прости бутони, нищо особено
- контролът за редактиране е прост, нищо особено
8.) Създайте база данни на MS Access със следните полета:
- Име на таблицата: тест
- Първо поле: ID
autonumber
,primary key
- Второ поле: поле
OLE Object
- Трето поле: съвет
text
това поле съхранява името на файла ( file.extension)
КАК ДА ИЗПОЛЗВАТЕ ТОВА ПРИЛОЖЕНИЕ:
Когато стартирате приложение, отворете About
елемент от менюто, за да може да изскочи диалогов прозорец. Изберете база данни, която създадохме.
Щракнете върху левия бутон (от синия кръг в изпратеното преди това изображение). Изскача диалогов прозорец за отваряне на файл и можете да изберете произволен файл (пробвал съм с .pdf
, .exe
, .zip
и jpeg
). Файлът трябва да бъде вмъкнат в базата данни.
За да прочетете BLOB и да го запишете на същото място, на което работи вашето приложение, въведете номера на записа, който искате да извлечете, и натиснете десния бутон (от червения кръг в изпратената преди това снимка). BLOB трябва да се зареди и след това да се запази на същото място, където е вашето приложение.
ЗАКЛЮЧИТЕЛНИ БЕЛЕЖКИ:
Това не е производствен код, моля, имайте предвид това. Това е само най-малкият, най-прост пример за код, който илюстрира проблема.
Отново, ако вмъкнете BLOB и след това се опитате да го заредите, нищо не се случва, но кодът се изпълнява без грешка.
Ако вмъкнете BLOB, след това затворете диалоговия прозорец, отворете диалоговия прозорец отново и след това опитайте да заредите BLOB от базата данни, всичко работи добре.
ВЪПРОС:
Как мога да пренапиша кода си, за да мога да вмъкна и след това да заредя BLOB, без да прибягвам до „решение №2“, описано по-рано.
РЕДАКТИРАНЕ:
Изпробвах приложението си на дял D и работи. Това означава, че проблемът е някъде в разрешенията. Можете ли да ми помогнете с това, защото нямам представа как да започна да решавам това?
КРАЙ НА РЕДАКТИРАНЕ
Благодаря ти.