2

私は、CDatabase および CRecordset クラスを使用してデータベース アクセスを行う MFC アプリに取り組んでいます。データベースは、MFC ベースのフォームまたはウィンドウに動的にバインドされません。

レコードの特定のフィールドが NULL であることの検出に問題があります。

私のコードのほとんどは正常に動作しています。データベースへの接続、クエリの発行、レコードの読み取りに問題はありません。ただし、ガベージ文字列を取得しているフィールドがいくつかあり、データベースをチェックすると、問題のフィールドが NULL であることがわかります。

場合によっては NULL が合理的であるため、それを防ぐのではなく、正しく処理するだけのコードが必要です。ただし、問題のフィールドのGetFieldValueから返される値はnull ではありません。有効なポインターではないランダムな値を取得します。どうやら、単純にポインター値をチェックするだけでなく、ある種の NULL のテストを行う必要があるようです。

IsFieldNullと呼ばれるCRecordsetクラスにメソッドがありますが、正しく動作していないようです。または、正しく呼び出していません。この方法がどのように使用されているかについて、オンラインで良い例は見つかりませんでした。ドキュメントには、「フィールドデータメンバー」を指すvoidポインターという単一のパラメーターを取ると書かれていますが、それがどうあるべきかについての定義はありません。ゼロベースのフィールド インデックスが渡される例と、フィールド名を持つ文字列定数が渡される例を見てきました。私はこれらのアイデアの両方を試しましたが、どちらもうまくいかないようです。

実際、CRecordset::IsFieldNull() を呼び出すと、常にコードがネバー ネバー ランドに飛んでいきます。

IsFieldStatusNullと呼ばれる CRecordset の別のメンバーがあり、これはフィールド インデックスを受け取るとされていますが、呼び出しも失敗することがわかりました。

最終的に、私の質問は、CRecordset の特定のフィールドが NULL かどうかをどのように確認するのですか?


既存のコードが質問に関連しているとは本当に思いませんが、リクエストされたので、ここにあります(try / catchブロックを削除するために簡略化されています):

CDBVariant v;
CRecordset theRecordSet(&theDB); // Pointer to my CDatabase object
query.Format("SELECT B.*, B.photographerWebsite AS website FROM gbm_shootphotographers AS A INNER JOIN gbm_photographers AS B ON A.photographerID=B.photographerID WHERE A.shootID=%d;", shootID );  
BOOL result = theRecordSet.Open(AFX_DB_USE_DEFAULT_TYPE, query );
memset(&v,0,sizeof(CDBVariant)); // Zero it out before retrieving field
// 1
theRecordSet.GetFieldValue("website", v);
// 2
CString website = *v.m_pstring;

「ウェブサイト」フィールドにデータがあるレコードの場合、問題なく取得されます。文字列は期待どおりです。ただし、「website」が NULL であるレコードの場合、空ではない文字列にガベージが含まれているか、さらに悪いことに、文字列ポインターが正しくありません。率直に言って、NULL の CDBVariant オブジェクトに何かを出力する理由がわかりません。分野ですが、そこに問題があります。

ロケーション #1 とロケーション #2 の両方でIsFieldNullIsFieldStatusNullを呼び出してみました。どちらにしても雑草の中に消えます。

4

1 に答える 1

5

データにアクセスする前に、そのメンバーCDBVariantを確認する必要があります。m_dwType

  • m_pstringtype がDBVT_STRING
  • DB フィールドが null の場合、バリアントはになりDBVT_NULL、アクセスに有効なメンバーはありません
  • など、 http://msdn.microsoft.com/en-US/library/4hhd4f44( v=vs.80 )を参照してください。

つまりunion、技術的にはいつでも任意のメンバーを読み取ることができますが、読み取るべきではないメンバーを読み取ると、未定義の動作が発生します。あなたの場合、ガベージ文字列に出力されるか、すぐにクラッシュする可能性のあるランダムなポインターを取得しています。

于 2012-08-10T06:57:50.013 に答える