次の方法で共有


TN054: MFC DAO クラスの使用中に DAO を直接呼び出す

DAO は Access データベースで使用され、Office 2013 でサポートされています。 DAO 3.6 は最終バージョンであり、古いと見なされます。 Visual C++ 環境とウィザードは DAO をサポートしていません (ただし、DAO クラスは含まれており、引き続き使用できます)。 新しいプロジェクトには 、OLE DB テンプレート または ODBC および MFC を使用することをお勧めします。 DAO は、既存のアプリケーションの保守にのみ使用する必要があります。

MFC DAO データベース クラスを使用する場合は、DAO を直接使用する必要がある場合があります。 通常、これは当てはまるわけではありませんが、MFC では、MFC クラスの使用を直接 DAO 呼び出しと組み合わせるときに、直接 DAO 呼び出しを簡単に行うためのヘルパー メカニズムがいくつか用意されています。 MFC で管理される DAO オブジェクトのメソッドに対して DAO を直接呼び出すには、数行のコードのみが必要です。 MFC で管理 されていない DAO オブジェクトを作成して使用する必要がある場合は、オブジェクトで Release を実際に呼び出すことで、もう少し作業を行う必要があります。 このテクニカル ノートでは、DAO を直接呼び出すタイミング、MFC ヘルパーが役立つ操作、DAO OLE インターフェイスの使用方法について説明します。 最後に、このメモでは、DAO セキュリティ機能のために DAO を直接呼び出す方法を示すサンプル関数をいくつか示します。

DAO を直接呼び出すタイミング

DAO の直接呼び出しを行う最も一般的な状況は、コレクションを更新する必要がある場合、または MFC でラップされていない機能を実装する場合に発生します。 MFC によって公開されない最も重要な機能はセキュリティです。 セキュリティ機能を実装する場合は、DAO ユーザー オブジェクトと Group オブジェクトを直接使用する必要があります。 セキュリティに加えて、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 呼び出しを行うときのリターン コードの確認、デバッグ出力のログ記録、予期されるエラーのチェック、必要に応じて適切な例外のスローに使用されます。 基になる 2 つのヘルパー関数と、これら 2 つのヘルパーのいずれかにマップされる 4 つのマクロがあります。 最適な説明は、コードを読み取るだけです。 DAO_CHECKDAO_CHECK_ERRORDAO_CHECK_MEM、および DAO_TRACE については、AFXDAO.H のマクロを参照してください。また、AfxDaoCheckAfxDaoTrace については、DAOCORE.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を返します。 DAO インターフェイスが想定される型の BSTR を取得することを保証するために、V_BSTRとV_BSTRTの 2 つのマクロが役立ちます。

V_BSTRは、COleVariant メンバーを抽出します。 このマクロは、通常、DAO インターフェイスのメソッドに COleVariant の内容を渡す必要がある場合に使用されます。 次のコード フラグメントは、V_BSTR マクロを利用する DAO DAOUser インターフェイスの 2 つのメソッドの宣言と実際の使用の両方を示しています。

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引数を使用すると、BSTRに ANSI COleVariantが存在することが保証されます(アプリケーションの ANSI バージョンをビルドする場合)。また、Unicode バージョンのアプリケーションをビルドする場合には、BSTRに Unicode が含まれることが保証されます。 これは DAO が期待する内容です。

もう 1 つのマクロV_BSTRT、ビルドの種類 (ANSI または Unicode) に応じて、の ANSI または Unicode COleVariant メンバーが抽出されます。 次のコードは、BSTRからCOleVariantCString値を抽出する方法を示しています。

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

V_BSTRTマクロと、 COleVariantに格納されている他の型を開くその他の手法を DAOVIEW サンプルで示します。 具体的には、この翻訳は CCrack::strVARIANT メソッドで実行されます。 このメソッドは、可能であれば、 COleVariant の値を CString のインスタンスに変換します。

DAO への直接呼び出しの簡単な例

基になる DAO コレクション オブジェクトを更新する必要がある場合に発生する可能性があります。 通常、これは必要ありませんが、必要な場合は簡単な手順です。 コレクションを更新する必要がある場合の例は、複数のユーザーが新しい tabledef を作成しているマルチユーザー環境で動作する場合です。 この場合、tabledefs コレクションが古くなる可能性があります。 コレクションを更新するには、特定のコレクション オブジェクトの Refresh メソッドを呼び出し、エラーを確認する必要があります。

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

現在、すべての DAO コレクション オブジェクト インターフェイスは、MFC DAO データベース クラスの文書化されていない実装の詳細であることに注意してください。

DAO セキュリティ機能に DAO を直接使用する

MFC DAO データベース クラスは DAO セキュリティ機能をラップしません。 DAO のセキュリティ機能を使用するには、DAO インターフェイスのメソッドを呼び出す必要があります。 次の関数は、システム データベースを設定し、ユーザーのパスワードを変更します。 この関数は他の 3 つの関数を呼び出し、その後定義されます。

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

    // ...
}

次の 4 つの例では、次の方法を示します。

  • システム 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();
}

こちらも参照ください

番号別テクニカル ノート
カテゴリ別テクニカル ノート