分享方式:


TN054:在使用 MFC DAO 類別時直接呼叫 DAO

注意

DAO 與 Access 資料庫搭配使用,並透過 Office 2013 支援。 DAO 3.6 是最終版本,而且被視為過時。 Visual C++ 環境和精靈不支援 DAO(雖然包含 DAO 類別,但您仍然可以使用這些類別)。 Microsoft 建議您針對新專案使用 OLE DB 範本 ODBC 和 MFC 。 您應該只使用 DAO 來維護現有的應用程式。

使用 MFC DAO 資料庫類別時,可能需要直接使用 DAO。 通常情況並非如此,但 MFC 提供了一些協助程式機制,有助於在結合 MFC 類別與直接 DAO 呼叫時,讓直接 DAO 呼叫變得簡單。 直接呼叫 MFC 管理的 DAO 物件方法時,只需要幾行程式碼。 如果您需要建立和使用 MFC 未 管理的 DAO 物件 ,您必須實際呼叫 Release 物件來執行更多工作。 此技術附注說明何時可能想要直接呼叫 DAO、MFC 協助程式可以做些什麼來協助您,以及如何使用 DAO OLE 介面。 最後,此附注提供一些範例函式,示範如何直接呼叫 DAO 以取得 DAO 安全性功能。

進行直接 DAO 呼叫的時機

進行直接 DAO 呼叫的最常見情況發生在需要重新整理集合時,或當您實作 MFC 未包裝的功能時。 MFC 未公開的最重要功能是安全性。 如果您想要實作安全性功能,您必須直接使用 DAO 使用者和 Group(s) 物件。 除了安全性之外,MFC 僅支援一些其他 DAO 功能。 其中包括記錄集複製和資料庫複寫功能,以及 DAO 的一些晚期新增功能。

DAO 和 MFC 實作的簡短概觀

MFC 的 DAO 包裝讓處理許多詳細資料更容易使用 DAO,因此您不需要擔心小事。 這包括 OLE 的初始化、DAO 物件的建立和管理(特別是集合物件)、錯誤檢查,以及提供強型別、更簡單的介面(沒有 VARIANT BSTR 引數)。 您可以進行直接 DAO 呼叫,但仍會利用這些功能。 您所有的程式碼都必須針對直接 DAO 呼叫所建立的任何物件呼叫 Release ,而且 不會 修改 MFC 在內部可能依賴的任何介面指標。 例如,除非您瞭解 所有 內部影響,否則請勿修改 開啟 CDaoRecordset 物件的m_pDAORecordset 成員。 不過, 您可以使用 m_pDAORecordset 介面直接呼叫 DAO 來取得 Fields 集合。 在此情況下, 不會修改m_pDAORecordset 成員。 當您完成 物件時,只需要在 Fields 集合物件上呼叫 Release

協助程式的描述,讓 DAO 呼叫更容易

為了讓呼叫 DAO 更容易提供的協助程式,與 MFC DAO 資料庫類別內部所使用的協助程式相同。 這些協助程式可用來在進行直接 DAO 呼叫、記錄偵錯輸出、檢查預期的錯誤,以及在必要時擲回適當的例外狀況時檢查傳回碼。 有兩個基礎協助程式函式和四個宏對應至這兩個協助程式之一。 最好的說明是只閱讀程式碼。 請參閱 AFXDAO 中的DAO_CHECK DAO_CHECK_ERROR DAO_CHECK_MEM DAO_TRACE 。若要查看宏,請參閱 DAOCORE 中的 AfxDaoCheck AfxDaoTrace 。Cpp。

使用 DAO OLE 介面

DAO 物件階層中每個物件的 OLE 介面定義于標頭檔 DBDAOINT 中。H,位於 \Program Files\Microsoft Visual Studio .NET 2003\VC7\include 目錄中。 這些介面提供方法,可讓您操作整個 DAO 階層。

對於 DAO 介面中的許多方法,您必須操作 BSTR 物件(OLE 自動化中使用的長度前置字串)。 物件 BSTR 通常會封裝在 VARIANT 資料類型內 。 MFC 類別 COleVariant 本身繼承自 VARIANT 資料類型。 根據您是否建置 ANSI 或 Unicode 的專案,DAO 介面會傳回 ANSI 或 Unicode BSTR s。 兩個宏,V_BSTR和V_BSTRT,有助於確保 DAO 介面取得 BSTR 預期的型別。

V_BSTR會擷 取 的 COleVariant bstrVal 成員。 當您需要將 的內容 COleVariant 傳遞至 DAO 介面的方法時,通常會使用此宏。 下列程式碼片段顯示 DAO DAOUser 介面的宣告和實際用法,這些方法會利用 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)));

請注意, VT_BSTRT 上述建構函式中指定的 COleVariant 引數可確保如果您建置應用程式的 ANSI 版本,以及應用程式的 Unicode BSTR 版本,中將會有 ANSI BSTR COleVariant 。 這是 DAO 預期的結果。

另一個宏V_BSTRT會根據建置的類型來擷取 ANSI 或 Unicode bstrVal 成員 COleVariant 。 下列程式碼示範如何將 值從 COleVariant 擷取 BSTRCString

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

V_BSTRT宏,以及其他開啟儲存在 COleVariant 中之其他類型的技術,會在 DAOVIEW 範例中示範。 具體而言,這個翻譯是在 方法中 CCrack::strVARIANT 執行。 如果可能,這個方法會將 的值 COleVariant 轉譯為 的 CString 實例。

直接呼叫 DAO 的簡單範例

需要重新整理基礎 DAO 集合物件時,可能會發生情況。 通常,這不應該是必要的,但如果有必要,這是一個簡單的程式。 當集合可能需要重新整理的範例是在多使用者環境中作業時,有多個使用者建立新的 tabledefs。 在此情況下,您的 tabledefs 集合可能會過時。 若要重新整理集合,您只需呼叫 Refresh 特定集合物件的 方法並檢查錯誤:

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

請注意,目前所有的 DAO 集合物件介面都是 MFC DAO 資料庫類別的未記載實作詳細資料。

直接針對 DAO 安全性功能使用 DAO

MFC DAO 資料庫類別不會包裝 DAO 安全性功能。 您必須呼叫 DAO 介面的方法,才能使用某些 DAO 安全性功能。 下列函式會設定系統資料庫,然後變更使用者的密碼。 此函式會呼叫後續定義的三個其他函式。

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

    // ...
}

接下來的四個範例示範如何:

  • 設定系統 DAO 資料庫 (。MDW 檔案)。

  • 設定預設使用者和密碼。

  • 變更使用者的密碼。

  • 變更 的密碼。MDB 檔案。

設定系統資料庫

以下是設定應用程式將使用之系統資料庫的範例函式。 在進行任何其他 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));
}

設定預設使用者和密碼

若要設定系統資料庫的預設使用者和密碼,請使用下列函式:

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

變更使用者的密碼

若要變更使用者的密碼,請使用下列函式:

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

變更 的密碼。MDB 檔案

若要變更 的密碼。MDB 檔案,請使用下列函式:

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

另請參閱

依編號顯示的技術提示
依分類區分的技術提示