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

Vedi anche

Note tecniche per numero
Note tecniche per categoria