CRecordset で、MDBファイルへ書き込むとき・・・


どら  2004-09-30 23:06:52  No: 54594

またまたの書き込みですみません(^^;

CRecordsetクラスを使って、AccessのMDBファイルに書き込みをしようとしています。

☆Accessで、新規mdbファイルを作成。
☆テーブルを一つ作成し、フィールド「data1」「data2」「data3」を作成。
☆コントロールパネル→管理ツール→データソース で、dsnを作成(ここでは「test」とします)
☆VC++6を起動、とりあえずMFCサポートのコンソールアプリケーションでプロジェクトを作成。
☆ClassWizerdで、CRecordsetクラス「CRec」を作成

といった手順で作成し、ソース中(関連部分のみ抜粋)では

CRec test;         //オブジェクトの作成
test.Open();
printf("ファイルオープン完了!!\n");
if(!test.CanAppend())
{
   printf("追加できません\n");
}
test.AddNew();

test.m_data1 = "一つ目";
test.m_data2 = "二つ目";
test.m_data3 = "三つ目";

if(!test.Update())
{
    printf("アップデートできませんでした。\n");
}
test.Requery();
rec.Close();

といった流れで作成しています。
コンパイルもビルドもうまくいくのですが、試しに動かしてみると・・・
テーブルとその中にフィールドだけを作成して中身がない状態で書き込まれると、エラーがおきて強制終了されてしまいます。
mdbファイルの中身を見るとしっかり更新されています。

また、1行でも中身がある状態だと、エラーもなく更新できます。
一番最初の時だけ、何か特別なことをしなければならないんでしょうか?
ご存じの方がいらっしゃいましたら、教えていただけませんでしょうか?


たく  2004-09-30 23:35:42  No: 54595

ぜんぜん詳しくないのですが、気になった点について

CanUpdateの必要はないのでしょうか?
また、RequeryはCDBException型の例外を送出するようですが、
これをcatchして詳細を見てはいかがでしょうか?


どら  2004-10-01 15:14:21  No: 54596

たくさん

最初の投稿のソースの部分で

if(!test.CanAppend())
{
   printf("追加できません\n");
}

と、きちんとCanUpdateはしています。

>  また、RequeryはCDBException型の例外を送出するようですが、
>  これをcatchして詳細を見てはいかがでしょうか?

こちらについては、もしよろしければ方法を教えていただけませんか?
MFC初心者なので、よく分かっていなくて・・・


たく  2004-10-01 19:51:06  No: 54597

例外のキャッチは次のような感じですが、

try{
  test.Requery();
}
catch(CDBException db_exp)
{
  printf("%s\n", db_exp.strError);
}

最後の
rec.Close();
は、
test.Close();
だったりしませんか?

前後のコードがわからないのでなんともいえませんが・・・


どら  2004-10-02 09:20:10  No: 54598

たくさん

>  最後の
>  rec.Close();
>  は、
>  test.Close();
>  だったりしませんか?

・・・です。
失礼しました(^^;

とりあえず、月曜に会社にいったらやってみますね♪
ありがとうございます(T_T)


どら  2004-10-05 04:49:32  No: 54599

いろいろ試してみたところ、
  test.Update();
のところでおかしくなっているようです。

たくさんに教えていただいた「try・・・」を試してみたところ、同様にポップアップで「Runtime Error!!」とでて、そこには

   This application has requested the Runtime to Terminate it in an usual way.
Plese contact the application's support team for more information.

とでて、OKボタンをクリックすると強制終了されます。
一体どこがいけないのでしょう・・・?


どら  2004-10-05 05:02:39  No: 54600

補足で・・・

> たくさんに教えていただいた「try・・・」を試してみたところ、

これは、まず

try{
  test.Requery();
}
catch(CDBException db_exp)
{
  db_exp.ReportError();
}

で試したところ、そこまで到達できず、次に

try{
  test.Update();
}
catch(CDBException db_exp)
{
  db_exp.ReportError();
}

で試したところ、やはり同じようになりました。

Updateの部分を消すと、強制終了が起こりません(当然、データは書き込まれませんが・・・)。

どなたか助けてください・・・


たく  2004-10-05 06:23:35  No: 54601

すみません、間違ってたようです。

try{
  test.Requery();
}
catch(CDBException* db_exp)
{
  db_exp->ReportError();
}

これでどうでしょうか?

ちなみに、最初のソースを
test.Close();
と変更しただけのサンプルはこちらで正しく動作しました^^;


どら  2004-10-05 19:08:08  No: 54602

試してみたところ、「変更または削除に失敗しました」とポップアップが上がってきます。

長〜区なってしまいますが、こちらがソースの抜粋です(変数も、ここで使うののみ記述しています)。

#define MAX_REC2 1024

//文字列時間(yy/mm/dd)をCTimeに格納する関数(動作確認済みです)
BOOL CtoTime(char *c_ymd, CTime *ymd);

CRec CRec;
int m, n, z;
FILE *LoadData;
char rec;
char rec2[MAX_REC2];

〜fopen、等は省略〜

m = 0;
n = 0;
z = 0;
while(1)
{
  rec = fgetc(LoadData);
  if(rec == EOF)
  {
     break;
  }
  //最初の2行は書き込まない
  if(m < 2)
  {
    if(rec == '\n')
    {
      m++;
    }
  }
  //3行目から書き込み
  else
  {
    if(rec == ',')
    {
      z++;
      for(; n < MAX_REC2; n++)
      {
        rec2[n] = '\0';
      }
      if(z >= 7)
      {
        printf("データのフォーマットが異常です①。:%s", argv[i]);
        getchar();  
        CRec.Close();
        return 1;
      }
      else if(z == 1)
      {
        CRec.m_Data1 = rec2;
      }
      else if(z == 2)
      {
        CRec.m_ata2 = rec2;
      }
      else if(z == 3)
      {
        CRec.m_Data3 = rec2;
      }
      else if(z == 4)
      {
        CRec.m_Data4 = rec2;
      }
      else if(z == 5)
      {
        CRec.m_Data5 = rec2;
      }
        else if(z == 6)
      {
        CRec.m_Data6 = rec2;
      }
      n = 0;
    }
    else if(rec == '\n')
    {
      if(z != 6)
      {
        printf("データのフォーマットが異常です②→%d。:%s", z, argv[i]);
        getchar();
        CRec.Close();
        return 1;
      }
      else
      {
        m++;
        for(; n < MAX_REC2; n++)
        {
          rec2[n] = '\0';
        }
        CtoTime(rec2, &CRec.m_Timedata);
        n = 0;
        z = 0;
        try
        {
          CRec.Update();
        }
        catch(CDBException *db_exp)
        {
          db_exp->ReportError();
        }
        CRec.Requery();
      }
    }
    else
    {
      rec2[n] = rec;
      n++;
    }
  }
}

抜けがあったらごめんなさい(^^;
やろうとしていることは

☆ある決まった形式のcsvファイルを読み込む
☆最初の2行は飛ばして3行目から一文字ずつ見ていく
   ○普通の文字列なら文字列変数rec2に追記
   ○「,」になったら、該当するAccessの項目に書き込み
   ○改行がでたら、その行の最後の項目は日付なので、
     AccessのDATEの形式に変換して書き込みをして、
     Updare、Requeryをして次の行へ・・・
☆以上をファイルがEOFになるまで繰り返す

といった感じです。

Update()の部分で突っかかっているみたいです・・・。
なぜなんでしょう・・・?


たく  2004-10-05 19:31:20  No: 54603

変換関数が動作確認済みで、
日付のフィールドに正しくセットされているということであれば
データベースのほうも確認してみたほうがよいのではないでしょうか?


どら  2004-10-06 18:41:25  No: 54604

途中から、全部のデータを保存できなくなってしまっていたのですが・・・
ODBC、プロジェクト(クラスも)すべてを新規作成して、ソースをコピーしたところ、とりあえず、mdbファイルに1行でもデータがあれば問題なく動きました。

ところが、やはりフィールドだけ存在し、1行もデータがない状態のテーブルに書き込みをしようとすると、Windowsお約束の「強制終了(エラーを送信する、とかでてくるやつ)」が現れてうまくいかないです・・・。

最初の1行目にデータを書き込む場合は、何か特別な処理をしなければならないんでしょうか・・・?


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加