Lettura di stringhe in un provider OLE DB
La CCustomRowset::Execute
funzione apre un file e legge le stringhe. Il consumer passa il nome file al provider chiamando ICommandText::SetCommandText. Il provider riceve il nome del file e lo archivia nella variabile m_strCommandText
membro . Execute
legge il nome del file da m_strCommandText
. Se il nome del file non è valido o il file non è disponibile, Execute
restituisce un errore. In caso contrario, apre il file e chiama fgets
per recuperare le stringhe. Per ogni set di stringhe che legge, Execute
crea un'istanza del record utente (modificato CCustomWindowsFile
dall'archiviazione di stringhe nel provider OLE DB) e lo inserisce in una matrice.
Se il file non può essere aperto, Execute
deve restituire DB_E_NOTABLE. Se restituisce invece E_FAIL, il provider non funzionerà con molti consumer e non supererà i test di conformità OLE DB.
Esempio
/////////////////////////////////////////////////////////////////////////
// CustomRS.h
class CCustomRowset : public CRowsetImpl< CCustomRowset, CCustomWindowsFile, CCustomCommand>
{
public:
HRESULT Execute(DBPARAMS * pParams, LONG* pcRowsAffected)
{
enum {
sizeOfBuffer = 256,
sizeOfFile = MAX_PATH
};
USES_CONVERSION;
FILE* pFile = NULL;
TCHAR szString[sizeOfBuffer];
TCHAR szFile[sizeOfFile];
size_t nLength;
ObjectLock lock(this);
// From a filename, passed in as a command text, scan the file
// placing data in the data array.
if (!m_strCommandText)
{
ATLTRACE("No filename specified");
return E_FAIL;
}
// Open the file
_tcscpy_s(szFile, sizeOfFile, m_strCommandText);
if (szFile[0] == _T('\0') ||
(fopen_s(&pFile, (char*)&szFile[0], "r") == 0))
{
ATLTRACE("Could not open file");
return DB_E_NOTABLE;
}
// Scan and parse the file.
// The file should contain two strings per record
LONG cFiles = 0;
while (fgets((char*)szString, sizeOfBuffer, pFile) != NULL)
{
nLength = strnlen((char*)szString, sizeOfBuffer);
szString[nLength-1] = '\0'; // Strip off trailing CR/LF
CCustomWindowsFile am;
_tcscpy_s(am.szCommand, am.iSize, szString);
_tcscpy_s(am.szCommand2, am.iSize, szString);
if (fgets((char*)szString, sizeOfBuffer, pFile) != NULL)
{
nLength = strnlen((char*)szString, sizeOfBuffer);
szString[nLength-1] = '\0'; // Strip off trailing CR/LF
_tcscpy_s(am.szText, am.iSize, szString);
_tcscpy_s(am.szText2, am.iSize, szString);
}
am.dwBookmark = ++cFiles;
if (!m_rgRowData.Add(am))
{
ATLTRACE("Couldn't add data to array");
fclose(pFile);
return E_FAIL;
}
}
if (pcRowsAffected != NULL)
*pcRowsAffected = cFiles;
return S_OK;
}
};
Al termine, il provider deve essere pronto per la compilazione e l'esecuzione. Per testare il provider, è necessario un consumer con funzionalità di corrispondenza. L'implementazione di un consumer semplice illustra come creare un consumer di test di questo tipo. Eseguire il consumer di test con il provider e verificare che il consumer di test recuperi le stringhe appropriate dal provider.
Dopo aver testato correttamente il provider, è possibile migliorarne le funzionalità implementando interfacce aggiuntive. Un esempio è illustrato in Miglioramento del provider di sola lettura semplice.