Dela via


TN054: Anropa DAO direkt när du använder MFC DAO-klasser

Anmärkning

DAO används med Access-databaser och stöds via Office 2013. DAO 3.6 är den slutliga versionen och anses vara föråldrad. Visual C++-miljön och guiderna stöder inte DAO (även om DAO-klasserna ingår och du fortfarande kan använda dem). Microsoft rekommenderar att du använder OLE DB-mallar eller ODBC och MFC för nya projekt. Du bör bara använda DAO för att underhålla befintliga program.

När du använder MFC DAO-databasklasserna kan det finnas situationer där det är nödvändigt att använda DAO direkt. Vanligtvis är detta inte fallet, men MFC har tillhandahållit några hjälpmekanismer för att underlätta att göra direkta DAO-anrop enkla när man kombinerar användningen av MFC-klasserna med direkta DAO-anrop. Att göra direkta DAO-anrop till metoderna för ett MFC-hanterat DAO-objekt bör bara kräva några rader kod. Om du behöver skapa och använda DAO-objekt som inte hanteras av MFC måste du utföra lite mer arbete genom att faktiskt anropa Release objektet. Den här tekniska anmärkningen förklarar när du kanske vill anropa DAO direkt, vad MFC-hjälparna kan göra för att hjälpa dig och hur du använder DAO OLE-gränssnitten. Slutligen innehåller den här anteckningen några exempelfunktioner som visar hur du anropar DAO direkt för DAO-säkerhetsfunktioner.

När du ska göra direkta DAO-anrop

De vanligaste situationerna för att göra direkta DAO-anrop inträffar när samlingar behöver uppdateras eller när du implementerar funktioner som inte omsluts av MFC. Den viktigaste funktionen som inte exponeras av MFC är säkerhet. Om du vill implementera säkerhetsfunktioner måste du använda DAO-användar- och gruppobjekten direkt. Förutom säkerhet finns det bara några andra DAO-funktioner som inte stöds av MFC. Dessa inkluderar funktioner för kloning av postuppsättningar och databasreplikering samt några sena tillägg till DAO.

En kort översikt över DAO och MFC:s implementering

MFC:s omslutning av DAO gör det enklare att använda DAO genom att ta hand om många detaljer så att du inte behöver oroa dig för detaljerna. Detta omfattar initiering av OLE, skapande och hantering av DAO-objekt (särskilt samlingsobjekt), felkontroll och tillhandahålla ett starkt skrivet, enklare gränssnitt (ingen VARIANT eller BSTR argument). Du kan göra direkta DAO-anrop och ändå dra nytta av dessa funktioner. Allt din kod måste göra är att anropa Release alla objekt som skapats av direkta DAO-anrop och inte ändra någon av de gränssnittspekare som MFC kan förlita sig på internt. Ändra till exempel inte m_pDAORecordset medlem i ett öppet CDaoRecordset objekt om du inte förstår alla interna konsekvenser. Du kan dock använda gränssnittet m_pDAORecordset för att anropa DAO direkt för att hämta fältinsamlingen. I det här fallet skulle m_pDAORecordset medlemsvariabel inte ändras. Du måste helt enkelt anropa Release samlingsobjektet Fält när du är klar med objektet.

Beskrivning av hjälpare för att göra DAO-anrop enklare

Hjälparna som tillhandahålls för att göra det enklare att anropa DAO är samma hjälppersonal som används internt i MFC DAO Database-klasserna. De här hjälparna används för att kontrollera returkoderna när du gör ett direkt DAO-anrop, loggar felsökningsutdata, söker efter förväntade fel och utlöser lämpliga undantag om det behövs. Det finns två underliggande hjälpfunktioner och fyra makron som mappas till en av dessa två hjälpfunktioner. Den bästa förklaringen är att helt enkelt läsa koden. Se DAO_CHECK, DAO_CHECK_ERROR, DAO_CHECK_MEM och DAO_TRACE i AFXDAO. H för att se makrona och se AfxDaoCheck och AfxDaoTrace i DAOCORE. CPP.

Använda DAO OLE-gränssnitten

OLE-gränssnitten för varje objekt i DAO-objekthierarkin definieras i huvudfilen DBDAOINT. H, som finns i katalogen \Program Files\Microsoft Visual Studio .NET 2003\VC7\include. Dessa gränssnitt innehåller metoder som gör att du kan ändra hela DAO-hierarkin.

För många av metoderna i DAO-gränssnitten måste du ändra ett BSTR objekt (en längdprefixsträng som används i OLE-automatisering). Objektet BSTR kapslas vanligtvis in i datatypen VARIANT . Själva MFC-klassen COleVariant ärver från datatypen VARIANT . Beroende på om du skapar projektet för ANSI eller Unicode returnerar DAO-gränssnitten ANSI eller Unicode BSTR. Två makron, V_BSTR och V_BSTRT, är användbara för att säkerställa att DAO-gränssnittet hämtar den BSTR förväntade typen.

V_BSTR extraherar bstrVal-medlemmen från en COleVariant. Det här makrot används vanligtvis när du behöver skicka innehållet i en COleVariant till en metod i ett DAO-gränssnitt. Följande kodfragment visar både deklarationerna och den faktiska användningen för två metoder i DAO DAOUser-gränssnittet som utnyttjar det V_BSTR makrot:

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

Observera att argumentet VT_BSTRT som anges i COleVariant konstruktorn ovan säkerställer att det finns en ANSI BSTR i COleVariant om du skapar en ANSI-version av ditt program och en Unicode BSTR för en Unicode-version av ditt program. Detta är vad DAO förväntar sig.

Det andra makrot, V_BSTRT, extraherar en bstrVal-medlem i antingen ANSI- eller Unicode-format beroende på byggtyp (ANSI eller Unicode). Följande kod visar hur du extraherar BSTR värdet från en COleVariant till en CString:

COleVariant varName(_T("MyName"), VT_BSTRT);
CString str = V_BSTRT(&varName);

Det V_BSTRT makrot, tillsammans med andra tekniker för att öppna andra typer som lagras i COleVariant, visas i DAOVIEW-exemplet. Mer specifikt utförs den här översättningen i CCrack::strVARIANT-metoden. Den här metoden översätter om möjligt värdet för en COleVariant till en instans av CString.

Enkelt exempel på ett direktanrop till DAO

Situationer kan uppstå när det är nödvändigt att uppdatera de underliggande DAO-samlingsobjekten. Normalt bör detta inte vara nödvändigt, men det är en enkel procedur om det är nödvändigt. Ett exempel på när en samling kan behöva uppdateras är när man arbetar i en fleranvändarmiljö där flera användare skapar nya tabelldefinitioner. I det här fallet kan din samling av tabelldefinitioner bli inaktuell. Om du vill uppdatera samlingen behöver du bara anropa Refresh metoden för det specifika samlingsobjektet och söka efter fel:

DAO_CHECK(pMyDaoDatabase->m_pDAOTableDefs->Refresh());

Observera att för närvarande är alla DAO-samlingsobjektgränssnitt odokumenterad implementeringsinformation för MFC DAO-databasklasserna.

Använda DAO direkt för DAO-säkerhetsfunktioner

MFC DAO-databasklasserna omsluter inte DAO-säkerhetsfunktioner. Du måste anropa metoder för DAO-gränssnitt för att använda vissa DAO-säkerhetsfunktioner. Följande funktion anger systemdatabasen och ändrar sedan användarens lösenord. Den här funktionen anropar tre andra funktioner, som senare definieras.

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

    // ...
}

De följande fyra exemplen visar hur du:

  • Ange systemets DAO-databas (. MDW-fil).

  • Ange standardanvändare och lösenord.

  • Ändra lösenordet för en användare.

  • Ändra lösenordet för en . MDB-fil.

Konfigurera systemdatabasen

Nedan visas en exempelfunktion för att ange den systemdatabas som ska användas av ett program. Den här funktionen måste anropas innan andra DAO-anrop görs.

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

Ange standardanvändare och lösenord

Om du vill ange standardanvändare och lösenord för en systemdatabas använder du följande funktion:

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

Ändra en användares lösenord

Om du vill ändra en användares lösenord använder du följande funktion:

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

Ändra lösenordet för en . MDB-fil

Så här ändrar du lösenordet för en . MDB-fil, använd följande funktion:

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

Se även

tekniska anteckningar efter nummer
tekniska anteckningar efter kategori