例外処理 : データベースの例外
この記事では、データベースの例外を処理する方法について説明します。 この記事の内容は、その多くが、ODBC (Open Database Connectivity) 用の MFC クラスと DAO (Data Access Objects) 用の MFC クラスの両方に当てはまります。 どちらか一方のモデルに固有の内容についてはその旨を明記してあります。 ここでは、次の内容について説明します。
例外処理の方法
DAO (旧) であれ ODBC であれアプローチは同じです。
必ず、例外的な条件を処理する例外ハンドラーを記述する必要があります。
データベースの例外をキャッチするうえで最も実用的なアプローチは、例外的なシナリオでアプリケーションをテストすることです。 コード内の操作で発生する可能性が高い例外を見極め、その例外を強制的に発生させます。 次に、トレース出力を観察して、どのような例外がスローされるかを確認するか、返されるエラー情報をデバッガーで観察します。 そうすることで、使用する例外シナリオに対して、どのようなリターン コードが表示されるかがわかります。
ODBC の例外に使用されるエラー コード
フレームワークで定義されているリターン コードには、AFX_SQL_ERROR_XXX 形式の名前が付いています。それらに加え、ODBC のリターン コードに基づく CDBExceptions もあります。 そうした例外のリターン コードには、SQL_ERROR_XXX という形式の名前が付けられています。
フレームワークで定義されているリターン コードであれ、ODBC で定義されているリターン コードであれ、データベース クラスから返される可能性のあるリターン コードは、CDBException
クラスの m_nRetCode データ メンバー下にドキュメント化されています。 ODBC で定義されているリターン コードの詳細については、「ODBC プログラマー リファレンス」を参照してください。
DAO の例外に使用されるエラー コード
DAO の例外については、通常、詳しい情報を入手できます。 キャッチした CDaoException オブジェクトの 3 つのデータ メンバーを介してエラー情報にアクセスできます。
m_pErrorInfo には、データベースに関する DAO エラー オブジェクトのコレクションにエラー情報をカプセル化する CDaoErrorInfo オブジェクトへのポインターが格納されています。
m_nAfxDaoError には、MFC DAO クラスからの拡張エラー コードが格納されます。 これらのエラー コードには、AFX_DAO_ERROR_XXX 形式の名前が付けられ、
CDaoException
のデータ メンバー下にドキュメント化されています。m_scode には、DAO からの OLE SCODE が格納されます (該当する場合)。 ただし、このエラーコードを使用する必要はほとんどありません。 通常、他の 2 つのデータ メンバーから、より詳しい情報を入手できます。 SCODE の値について詳しくは、このデータ メンバーを参照してください。
その他 DAO エラーについての情報や、DAO エラー オブジェクトの型、DAO Errors コレクションが CDaoException クラスから得られます。
データベースの例外処理の例
次の例では、new
演算子を使用して、CRecordset から派生したオブジェクトをヒープに構築し、(ODBC データ ソースの) レコードセットを開こうとしています。 DAO クラスの同様の例については、後述の「DAO 例外の例」を参照してください。
ODBC 例外の例
Open メンバー関数から (ODBC クラスの CDBException 型の) 例外がスローされる可能性があるため、このコードでは、Open
呼び出しを try
ブロックに入れています。 CDBException
は、後続の catch
ブロックによってキャッチされます。 例外オブジェクト自体 (e
) を詳しく調べることもできますが、このケースでは、レコードセットの作成に失敗したことがわかれば十分です。 catch
ブロックでは、メッセージ ボックスを表示し、レコードセット オブジェクトを削除してクリーンアップを実行しています。
CRecordset* CMyDatabaseDoc::GetRecordset()
{
CCourses* pSet = new CCourses(&m_dbCust);
try
{
pSet->Open();
}
catch (CDBException* e)
{
AfxMessageBox(e->m_strError, MB_ICONEXCLAMATION);
// Delete the incomplete recordset object
delete pSet;
pSet = NULL;
e->Delete();
}
return pSet;
}
DAO 例外の例
DAO の例は、ODBC の例と似ていますが、通常、より多くの種類の情報を取得できます。 こちらも、レコードセットを開くことを試みるコードとなっています。 その試みで例外がスローされた場合、例外オブジェクトのデータ メンバーを調べることでエラー情報を得ることができます。 前の ODBC の例と同様、レコードセットの作成に失敗したことがわかれば十分でしょう。
CDaoRecordset* CMyDaoDatabaseDoc::GetRecordset()
{
CDaoRecordset* pSet = new CCustSet(&m_db);
try
{
pSet->Open();
}
catch (CDaoException* pe)
{
AfxMessageBox(pe->m_pErrorInfo->m_strDescription, MB_ICONEXCLAMATION);
// Delete the incomplete recordset object
delete pSet;
pSet = NULL;
pe->Delete();
}
return pSet;
}
このコードは、例外オブジェクトの m_pErrorInfo メンバーからエラー メッセージ文字列を取得します。 このメンバーの値は、MFC によって例外がスローされるときに設定されます。
CDaoException
オブジェクトから返されるエラー情報の説明については、CDaoException クラスと CDaoErrorInfo クラスのページを参照してください。
Microsoft Jet (.mdb) データベースを操作するときに存在するエラー オブジェクトは 1 つだけです。また、ODBC を操作するときも、多くの場合、エラー オブジェクトは 1 つしか存在しません。 まれなケースとして、ODBC データ ソースを使用していて複数のエラーが存在する場合は、CDaoException::GetErrorCount で返されるエラー数に基づいて DAO の Errors コレクションをループできます。 ループの反復ごとに、CDaoException::GetErrorInfo を呼び出して、m_pErrorInfo
データ メンバーの値を設定します。