TN054: chiamata a DAO diretta durante l'utilizzo delle classi DAO MFC
Nota
DAO viene usato con i database di Access ed è supportato tramite Office 2013. DAO 3.6 è la versione finale e viene considerata obsoleta. L'ambiente e le procedure guidate di Visual C++ non supportano DAO (anche se le classi DAO sono incluse ed è comunque possibile usarle). Microsoft consiglia di usare i modelli OLE DB o ODBC e MFC per i nuovi progetti. È consigliabile usare DAO solo per gestire le applicazioni esistenti.
Quando si usano le classi di database DAO MFC, possono verificarsi situazioni in cui è necessario usare direttamente DAO. In genere, questo non sarà il caso, ma MFC ha fornito alcuni meccanismi helper per facilitare l'esecuzione di chiamate DAO dirette quando si combina l'uso delle classi MFC con chiamate DAO dirette. L'esecuzione di chiamate DAO dirette ai metodi di un oggetto DAO gestito da MFC deve richiedere solo poche righe di codice. Se è necessario creare e usare oggetti DAO che non sono gestiti da MFC, è necessario eseguire un po ' di più chiamando Release
effettivamente sull'oggetto . Questa nota tecnica spiega quando si potrebbe voler chiamare direttamente DAO, cosa possono fare gli helper MFC per aiutarti e come usare le interfacce OLE DAO. Infine, questa nota fornisce alcune funzioni di esempio che illustrano come chiamare DAO direttamente per le funzionalità di sicurezza DAO.
Quando effettuare chiamate DAO dirette
Le situazioni più comuni per effettuare chiamate DAO dirette si verificano quando è necessario aggiornare le raccolte o quando si implementano funzionalità non incluse in MFC. La funzionalità più significativa non esposta da MFC è la sicurezza. Se si desidera implementare le funzionalità di sicurezza, è necessario usare direttamente gli oggetti DAO User(s) e Group(s). Oltre alla sicurezza, esistono solo alcune altre funzionalità DAO non supportate da MFC. Tra cui la clonazione di recordset e le funzionalità di replica del database, oltre ad alcune aggiunte in ritardo a DAO.
Breve panoramica dell'implementazione di DAO e MFC
Il wrapping di DAO di MFC semplifica l'uso di DAO gestendo molti dei dettagli in modo da non doversi preoccupare delle piccole cose. Ciò include l'inizializzazione di OLE, la creazione e la gestione degli oggetti DAO (in particolare gli oggetti della raccolta), il controllo degli errori e la fornitura di un'interfaccia fortemente tipizzata e più semplice (nessun argomento o BSTR
VARIANT). È possibile effettuare chiamate DAO dirette e sfruttare comunque queste funzionalità. Tutto il codice deve essere chiamato Release
per tutti gli oggetti creati da chiamate DAO dirette e non modificare alcun puntatore di interfaccia che MFC può basarsi internamente. Ad esempio, non modificare il membro m_pDAORecordset di un oggetto aperto CDaoRecordset
, a meno che non si comprendano tutte le ramificazioni interne. È tuttavia possibile usare l'interfaccia m_pDAORecordset per chiamare direttamente DAO per ottenere l'insieme Fields. In questo caso il membro m_pDAORecordset non verrà modificato. È sufficiente chiamare Release
sull'oggetto insieme Fields al termine dell'oggetto .
Descrizione degli helper per semplificare le chiamate DAO
Gli helper forniti per semplificare la chiamata a DAO sono gli stessi helper usati internamente nelle classi di database DAO MFC. Questi helper vengono usati per controllare i codici restituiti quando si effettua una chiamata DAO diretta, registrando l'output di debug, verificando gli errori previsti e generando eccezioni appropriate, se necessario. Esistono due funzioni helper sottostanti e quattro macro che eseguono il mapping a uno di questi due helper. La spiegazione migliore consiste nel leggere semplicemente il codice. Vedere DAO_CHECK, DAO_CHECK_ERROR, DAO_CHECK_MEM e DAO_TRACE in AFXDAO. H per visualizzare le macro e vedere AfxDaoCheck e AfxDaoTrace in DAOCORE. CPP.
Uso delle interfacce OLE DAO
Le interfacce OLE per ogni oggetto nella gerarchia di oggetti DAO sono definite nel file di intestazione DBDAOINT. H, disponibile nella directory \Programmi\Microsoft Visual Studio .NET 2003\VC7\include. Queste interfacce forniscono metodi che consentono di modificare l'intera gerarchia DAO.
Per molti dei metodi nelle interfacce DAO, è necessario modificare un BSTR
oggetto (una stringa con prefisso di lunghezza usata nell'automazione OLE). L'oggetto BSTR
viene in genere incapsulato all'interno del tipo di dati VARIANT . La classe COleVariant
MFC eredita dal tipo di dati VARIANT . A seconda che si crei il progetto per ANSI o Unicode, le interfacce DAO restituiranno ANSI o Unicode BSTR
. Due macro, V_BSTR e V_BSTRT, sono utili per garantire che l'interfaccia DAO ottenga il BSTR
del tipo previsto.
V_BSTR estrae il membro bstrVal di un oggetto COleVariant
. Questa macro viene in genere utilizzata quando è necessario passare il contenuto di un COleVariant
oggetto a un metodo di un'interfaccia DAO. Il frammento di codice seguente mostra sia le dichiarazioni che l'uso effettivo per due metodi dell'interfaccia DAO DAOUser che sfruttano la macro V_BSTR:
COleVariant varOldName;
COleVariant varNewName(_T("NewUser"), VT_BSTRT);
// Code to assign pUser to a valid value omitted DAOUser *pUser = NULL;
// These method declarations were taken from DBDAOINT.H
// STDMETHOD(get_Name) (THIS_ BSTR FAR* pbstr) PURE;
// STDMETHOD(put_Name) (THIS_ BSTR bstr) PURE;
DAO_CHECK(pUser->get_Name(&V_BSTR (&varOldName)));
DAO_CHECK(pUser->put_Name(V_BSTR (&varNewName)));
Si noti che l'argomento VT_BSTRT
specificato nel COleVariant
costruttore precedente garantisce che sia presente un ANSI BSTR
nel COleVariant
se si compila una versione ANSI dell'applicazione e un unicode per una versione Unicode BSTR
dell'applicazione. Questo è ciò che aspetta DAO.
L'altra macro, V_BSTRT, estrae un membro ANSI o Unicode bstrVal a COleVariant
seconda del tipo di compilazione (ANSI o Unicode). Il codice seguente illustra come estrarre il BSTR
valore da un COleVariant
oggetto in :CString
COleVariant varName(_T("MyName"), VT_BSTRT);
CString str = V_BSTRT(&varName);
La macro V_BSTRT, insieme ad altre tecniche per aprire altri tipi archiviati in COleVariant
, è illustrata nell'esempio DAOVIEW. In particolare, questa traduzione viene eseguita nel CCrack::strVARIANT
metodo . Questo metodo, se possibile, converte il valore di un oggetto COleVariant
in un'istanza di CString
.
Semplice esempio di chiamata diretta a DAO
Le situazioni possono verificarsi quando è necessario aggiornare gli oggetti raccolta DAO sottostanti. In genere, questo non dovrebbe essere necessario, ma è una procedura semplice se necessario. Un esempio di quando è necessario aggiornare una raccolta è quando si opera in un ambiente multiutente con più utenti che creano nuovi tabledef. In questo caso l'insieme tabledefs potrebbe diventare obsoleto. Per aggiornare la raccolta, è sufficiente chiamare il Refresh
metodo dell'oggetto raccolta specifico e verificare la presenza di errori:
DAO_CHECK(pMyDaoDatabase->m_pDAOTableDefs->Refresh());
Si noti che attualmente tutte le interfacce oggetto raccolta DAO sono dettagli di implementazione non documentati delle classi di database DAO MFC.
Uso diretto di DAO per le funzionalità di sicurezza DAO
Le classi di database DAO MFC non eseguono il wrapping delle funzionalità di sicurezza DAO. È necessario chiamare i metodi delle interfacce DAO per usare alcune funzionalità di sicurezza DAO. La funzione seguente imposta il database di sistema e quindi modifica la password dell'utente. Questa funzione chiama altre tre funzioni, che vengono successivamente definite.
void ChangeUserPassword()
{
// Specify path to the Microsoft Access *// system database
CString strSystemDB =
_T("c:\\Program Files\\MSOffice\\access\\System.mdw");
// Set system database before MFC initilizes DAO
// NOTE: An MFC module uses only one instance
// of a DAO database engine object. If you have
// called a DAO object in your application prior
// to calling the function below, you must call
// AfxDaoTerm to destroy the existing database
// engine object. Otherwise, the database engine
// object already in use will be reused, and setting
// a system datbase will have no effect.
//
// If you have used a DAO object prior to calling
// this function it is important that DAO be
// terminated with AfxDaoTerm since an MFC
// module only gets one copy of the database engine
// and that engine will be reused if it hasn't been
// terminated. In other words, if you do not call
// AfxDaoTerm and there is currently a database
// initialized, setting the system database will
// have no effect.
SetSystemDB(strSystemDB);
// User name and password manually added
// by using Microsoft Access
CString strUserName = _T("NewUser");
CString strOldPassword = _T("Password");
CString strNewPassword = _T("NewPassword");
// Set default user so that MFC will be able
// to log in by default using the user name and
// password from the system database
SetDefaultUser(strUserName, strOldPassword);
// Change the password. You should be able to
// call this function from anywhere in your
// MFC application
ChangePassword(strUserName, strOldPassword, strNewPassword);
// ...
}
I quattro esempi successivi illustrano come:
Impostare il database DAO di sistema (. File MDW).
Impostare l'utente e la password predefiniti.
Modificare la password di un utente.
Modificare la password di un oggetto . File MDB.
Impostazione del database di sistema
Di seguito è riportata una funzione di esempio per impostare il database di sistema che verrà usato da un'applicazione. Questa funzione deve essere chiamata prima che vengano effettuate altre chiamate DAO.
// Set the system database that the
// DAO database engine will use
void SetSystemDB(CString& strSystemMDB)
{
COleVariant varSystemDB(strSystemMDB, VT_BSTRT);
// Initialize DAO for MFC
AfxDaoInit();
DAODBEngine* pDBEngine = AfxDaoGetEngine();
ASSERT(pDBEngine != NULL);
// Call put_SystemDB method to set the *// system database for DAO engine
DAO_CHECK(pDBEngine->put_SystemDB(varSystemDB.bstrVal));
}
Impostazione dell'utente e della password predefiniti
Per impostare l'utente e la password predefiniti per un database di sistema, usare la funzione seguente:
void SetDefaultUser(CString& strUserName,
CString& strPassword)
{
COleVariant varUserName(strUserName, VT_BSTRT);
COleVariant varPassword(strPassword, VT_BSTRT);
DAODBEngine* pDBEngine = AfxDaoGetEngine();
ASSERT(pDBEngine != NULL);
// Set default user:
DAO_CHECK(pDBEngine->put_DefaultUser(varUserName.bstrVal));
// Set default password:
DAO_CHECK(pDBEngine->put_DefaultPassword(varPassword.bstrVal));
}
Modifica della password di un utente
Per modificare la password di un utente, usare la funzione seguente:
void ChangePassword(CString &strUserName,
CString &strOldPassword,
CString &strNewPassword)
{
// Create (open) a workspace
CDaoWorkspace wsp;
CString strWspName = _T("Temp Workspace");
wsp.Create(strWspName, strUserName, strOldPassword);
wsp.Append();
// Determine how many objects there are *// in the Users collection
short nUserCount;
short nCurrentUser;
DAOUser *pUser = NULL;
DAOUsers *pUsers = NULL;
// Side-effect is implicit OLE AddRef()
// on DAOUser object:
DAO_CHECK(wsp.m_pDAOWorkspace->get_Users(&pUsers));
// Side-effect is implicit OLE AddRef()
// on DAOUsers object
DAO_CHECK(pUsers->getcount(&nUserCount));
// Traverse through the list of users
// and change password for the userid
// used to create/open the workspace
for(nCurrentUser = 0; nCurrentUser <nUserCount; nCurrentUser++)
{
COleVariant varIndex(nCurrentUser, VT_I2);
COleVariant varName;
// Retrieve information for user nCurrentUser
DAO_CHECK(pUsers->get_Item(varIndex, &pUser));
// Retrieve name for user nCurrentUser
DAO_CHECK(pUser->get_Name(&V_BSTR(&varName)));
CString strTemp = V_BSTRT(&varName);
// If there is a match, change the password
if (strTemp == strUserName)
{
COleVariant varOldPwd(strOldPassword, VT_BSTRT);
COleVariant varNewPwd(strNewPassword, VT_BSTRT);
DAO_CHECK(pUser->NewPassword(V_BSTR(&varOldPwd),
V_BSTR(&varNewPwd)));
TRACE("\t Password is changed\n");
}
}
// Clean up: decrement the usage count
// on the OLE objects
pUser->Release();
pUsers->Release();
wsp.Close();
}
Modifica della password di un oggetto . MDB File
Per modificare la password di un oggetto . Il file MDB usa la funzione seguente:
void SetDBPassword(LPCTSTR pDB,
LPCTSTR pszOldPassword,
LPCTSTR pszNewPassword)
{
CDaoDatabase db;
CString strConnect(_T(";pwd="));
// the database must be opened as exclusive
// to set a password
db.Open(pDB, TRUE, FALSE, strConnect + pszOldPassword);
COleVariant NewPassword(pszNewPassword, VT_BSTRT),
OldPassword(pszOldPassword, VT_BSTRT);
DAO_CHECK(db.m_pDAODatabase->NewPassword(V_BSTR(&OldPassword),
V_BSTR(&NewPassword)));
db.Close();
}