ADO.NETのデータベースについて

このQ&Aのポイント
  • ADO.NETでデータベースの作成とフィールドの変更、更新がうまくいかない問題が発生
  • プログラムの内容はAccessデータからの表の読み込みと挿入、変更、削除、データの更新
  • 原因を教えていただけると助かります
回答を見る
  • ベストアンサー

ADO.NETのデータベースについて

 こんにちは。いつもお世話になっております。  プログラミングの初心者で、現在VC++でプログラムを作成しています。環境は、OSがWindowsXP、統合環境はVisualStudio2008 Professionalを使用しています.  ADO.NETでデータベースを作成しているのですが、DataSetを介して、任意のフィールドを変更・更新がうまくいきません。プログラムの内容は、保存されているAccessデータから表を読み込み、その表に対して挿入、変更、削除を行い、最後にupdateをしてAccessのデータを更新するというものです。以下、プログラムの一部を抜粋します。拙い説明で申し訳ありません。原因が分かる方、よろしくご教授ください。 m(_)m private: bool LoadAccessFile(String^ path) { // コネクションを作成 OleDbConnection^ cn = gcnew OleDbConnection(); cn->ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" "Data Source=" + path; // すべてのデータを読み込む OleDbDataAdapter^ da = gcnew OleDbDataAdapter("select * from 実績テーブル", cn); OleDbDataAdapter^ da2 = gcnew OleDbDataAdapter("select * from クエリ1", cn); OleDbCommandBuilder^ builder = gcnew OleDbCommandBuilder(da); //test OleDbCommand^ selectCommand = cn->CreateCommand(); OleDbCommand^ selectCommand2 = cn->CreateCommand(); OleDbCommand^ insertCommand = cn->CreateCommand(); OleDbCommand^ updateCommand = cn->CreateCommand(); OleDbCommand^ deleteCommand = cn->CreateCommand(); selectCommand->CommandText = "select 通し番号, 日付, 内容, 金額, カテゴリー番号, 銀行口座通し番号 from 実績テーブル where 通し番号=2"; selectCommand2->CommandText = "select 通し番号, 日付, 内容, 金額, カテゴリー名称, 銀行口座口座名称 from クエリ1"; insertCommand->CommandText = "insert into 実績テーブル (通し番号, 日付, 内容, 金額, カテゴリー番号, 銀行口座通し番号) values (@通し番号, @日付, @内容, @金額, @カテゴリー番号, @銀行口座通し番号)";      (中略) // OleDbDataAdapterのスキーマと、SelectCommandで抽出したデータを格納 da->FillSchema(ds, System::Data::SchemaType::Mapped); da->Fill(ds->Tables["Table"]); // "Table"表の2行3列目のデータを変更 ds->Tables->Add("クエリ1"); //test(090223) DataRow^ row = ds->Tables["Table"]->Rows[1]; //Rows[0]の添え字を0以外にするとエラー。「位置1に行がありません」 DataColumn^ column = ds->Tables["Table"]->Columns[2]; row[column] = "本"; // "Table"表の0行目を削除 ds->Tables["Table"]->Rows[0]->Delete(); //Rows[0]の添え字を0以外にするとエラー。「位置1に行がありません」

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

dsに取得するデータが where句で選別されているので これにより 1行しか返さないのではないかと思います 『通し番号』とあるので テーブルの中で一意の値なのでしょう OleDbCommanBuilderの使い方をリファレンスで確認しましょう //test 部分の selectCommand等を daやda2の各コマンドに再設定しているのであれば間違った使い方の可能性が高いです daの生成時に選択クエリーを与えたのであればSelectCommandプロパティが生成されています このdaを与えてCommnadBuilderを生成する時点で daのSelectCommand,InsertCommand,UpdateCommand,DeleteCommandが更新されるはずです

watataku70
質問者

補足

 redfox63さん、回答ありがとうございます。m(_)m  ds->Tables["Table"]->Rows[1]->Delete(); のRowsの添え字を0以外に設定するとエラーになる件は、redfox63さんご指摘の通り、selectCommand->CommandTextでwhere句を使い1行のみを抽出していたためでした。where句を削除することによって意図したデータの変更ができました。ありがとうございました。m(_)m  また、質問を重ねてしまい申し訳ないのですが、CommnadBuilderについて一つ質問させてください。 OleDbCommandBuilder^ builder = gcnew OleDbCommandBuilder(da); のようにOleDbCommandBuilderをインスタンス化して、SelectCommandを手動で用意すると、InsertCommand,UpdateCommand,DeleteCommandが自動的に生成されると、リファレンスに書かれていたのですが、InsertCommand,UpdateCommand,DeleteCommandは、SelectCommand設定後に使用できるようになるということでしょうか? また、InsertCommand,UpdateCommand,DeleteCommandは、生成後はパラメーターやスキーマの情報は、SelectCommandに設定された情報を取得して使用するのでしょうか? 以上、お手数ですがご回答いただければ幸いです。m(_)m  

その他の回答 (3)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

確認のため簡単なプロジェクトを組んでやってみましたが どうも Adpter/CommandBulider経由でやると Updateなどが上手く機能しないような状況になってしまいます そこで プロジェクト > 追加 > 新しいの項目 > データセット を追加し このxsdファイルに TableAdapterを追加 ウィザードで SQLなどを指定 フォームへのデータ表示更新のために 『データ ソース』から追加 といった手順で BindingSource経由にしてみたところ Updateも問題なくいくようです 既存のAdapterクラスのUpdateメソッドに対しての設定が足りないのだろうと思いますが調べきれておりません m(__)m

watataku70
質問者

お礼

 redfox63さん、回答ありがとうございます。m(_)m  お手数をお掛けしてしまい申し訳ありませんでした。私も色々やってみたのですが、CommandBulider経由でのUpdateは、うまくいきませんでした。もう少しUpdateメソッドについて調べてみようと思います。ありがとうございました。m(_)m

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

ごめんなさい m(__)m 少々勘違いがあったようです CommandBuilderを生成した時点でDataAtdpterのCommand群は更新されません builder = gcnew OleDbCommandBuilder(da); を行って da->InsertCommand = builder->GetInsertCommand(); da->DeleteCommand = builder->GetDeleteCommand(); da->UpdateCommand = builder->GetUpdateCommand(); といった具合に自動生成されたコマンド群を設定してください

watataku70
質問者

補足

 redfox63さん、回答ありがとうございます。m(_)m  リファレンスではSelectCommandの設定後、InsertCommand、DeleteCommand、UpdateCommandが自動生成されるとあるのですが、その場合でもInsertCommand、DeleteCommand、UpdateCommandは、 builder->GetInsertCommand(); のように設定が必要ということでしょうか?  また、生成されたInsertCommand、DeleteCommand、UpdateCommandの初期値はどのような中身が設定されるのでしょうか?質問を重ねてしまい申し訳ないのですが、よろしくお願いいたします。m(_)m  

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

アクセスのデータを クエリから取得しているのでしょうか? クエリからでは Update等の更新は出来そうに無いと思います クエリーのSQLを使って DataSetを取得しましょう 2行目などの取得が出来ないとのことですが ds->Tables["Table"]->Rows.Count の値はいくつになっているのでしょう

watataku70
質問者

補足

redfox63さん、早速の回答ありがとうございます。m(_)m Accessのデータは、テーブルからds(DataSet)にデータを取得しています。dsの変更後、dsに対してupdateを実行して、外部キーを持っているクエリ1をVC++のDataGridViewに表示させています。(データベースに不慣れなので間違っていればご指摘くださいm(_)m) もう一つ、ご指摘のあったテーブルのカレントの行を以下の方法で調べて見たのですが、「1」となっていました。 int i = ds->Tables["Table"]->Rows->Count;

関連するQ&A

  • OleDbDataAdapterのエラー

    OS:Windows7 Visual Studio2012Professional いつもこちらでお世話になっています。 OleDbプロバイダーのOleDbDataAdapterでAccessファイルからDataSetへデータを取込む作業をしています。 下記のコードで、一度はDataSetへデータを取り込めたのですが、接続文字列を変更したところ、変更前の接続文字列(パス)を参照に行ってしまいエラーになります。 リビルドしたり、プロジェクトを作成し直したりしましたが、やはり変更前の接続文字列を使用してしまいます。 【コード】 private void Form1_Load ( object sender, EventArgs e ) {  string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\hoge変更後\○○.mdb;"  string sql = @"SELECT * FROM Table;";  DataSet ds = new DataSet();  OleDbConnection cn = new OleDbConnection();  cn.ConnectionString = connectionString;  OleDbCommand cmd = new OleDbCommand();  using (OleDbDataAdapter da = new OleDbDataAdapter()) {  cmd.Connection = cn;  cmd.CommandText = sql;  da.SelectCommand = cmd;  da.Fill( ds ); ← ここで『System.Data.OleDb.OleDbException』エラー   } this.dataGridView.DataSource = ds.Tables[0]; } 【エラー】 System.Data.OleDb.OleDbException はハンドルされませんでした。 HResult=-2147467259 Message=パス 'D:\hoge前\○○.mdb' は正しくありません。パス名に間違いがないことと、ファイルが置かれたサーバーに接続していることを確認してください。 Source=Microsoft JET Database Engine ErrorCode=-2147467259 どなたか原因がおわかりになりますでしょうか。 どうぞよろしくお願いいたします。

  • .NET MDBデータベース更新について質問です

    DataGridViewで表示するところまでできたのですが DataGridView上で編集したものを更新ボタンで MDBデータベースに上書き保存という形で 行いたいのですがいろいろ調べてもわかりませんでした。 VBを初めて日が浅いのでこつこつ勉強中なのですが 業務上の都合でDBの作成を行っています。 基本的に書き直したもの 'データベース取得 Dim Cn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=保存場所" ) Dim Cm As OleDbCommand = Cn.CreateCommand Dim Adapter As New OleDbDataAdapter(Cm) Dim Table As New DataTable Cn.Open() Cm.CommandText = "SELECT * FROM Aテーブル" Adapter.Fill(Table) DataGridView1.DataSource = Table DBにはこのように接続しております。 ここまでも手探りで行ったので熟練の方から見ればへんかもしれませんが指導おねがいします。

  • DataSet ds = new DataSet();

    DataSet ds = new DataSet(); System.Data.OleDb.OleDbDataAdapter da = new System.Data.OleDb.OleDbDataAdapter(); da.SelectCommand = cmd; da.Fill(ds); でデータを格納したときに、 重複データを省きたいのですが可能でしょうか? DataReader ならひとつひとつ格納していくので、 重複データを省くことができるのですが。

  • VB2005とADO.NETを使った時のSELECT文の書き方で分らないことがあり困っています

    VB2005とADO.NETを本で勉強中の超初心者です。本のサンプルを参考に以下のようなコ-ドを作って動作させるとDataGridViewにDBの内容が正しく表示されますが、 Dim cn As New OleDbConnection cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _ & "Data Source=C:\VB2005\Order.mdb" Dim da As OleDbDataAdapter da = New OleDbDataAdapter("SELECT * FROM Goods;", cn) Dim ds As New DataSet da.Fill(ds, "Goods") DataGridView1.DataSource = ds.Tables("Good 特定のコ-ドをFormのテキストボックスから入力して、表示させたいと思い"SELECT * FROM Goods WHERE GoodsId = TextBox1.Text;"とするとエラ-になってしまいました。ちなみに"SELECT * FROM Goods WHERE GoodsId = 'A0001';として動作させるとA0001だけを表示することはできました。 どのようにすればテキストボックスや変数で、表示したいコ-ドを指定したら良いか教えて頂けないでしょうか。

  • vb.net で ADO でアクセスのテーブル

    アクセスのテーブルのレコードの数を取得したいのですが コードがわからないので続きを教えていただけますか? Imports System.Data.OleDb Sub test() Dim oleConn As OleDbConnection Dim oleCmd As OleDbCommand Dim oleAdp As OleDbDataAdapter oleConn = New OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0;" & "Data Source=C:\Database1.accdb;") oleCmd = oleConn.CreateCommand() oleCmd.CommandText = "SELECT * FROM テーブル1" oleAdp = New OleDbDataAdapter(oleCmd) 'MsgBox oleCmd.??? End Sub までできたのですが、ここからどうすれば数を取得できますか?

  • 複数テーブルにある個別フィールドを一度で更新

    VB.NET2005で開発しております。 複数テーブルにある個別フィールドを一度で更新したいと考えておりますが、JOIN等使用してみたところ上手く行かず困っております。 一度で複数テーブルを更新する事は可能でしょうか? 更新する  更新する テーブル名 フィールドと値 共通キー table1   coulmn2 = A   coulmn1 table2   coulmn3 = B   coulmn1 table3   coulmn4 = C coulmn1 -------------------------------- connect = Me.DbConnect command = connect.CreateCommand command.CommandText = "UPDATE TABLE1, TABLE2 ・・・" da = factory.CreateDataAdapter() da.SelectCommand = command ds = New DataSet da.Fill(ds) conn.Close()

  • VB2008でMDBのオ-トナンバの項目をキ-にして読み込めなくて困っています

    VB2008とADO.NETを勉強中の超初心者です。 MDBのオ-トナンバの項目をキ-にして、読み込みたいと思って以下のようなプログラムを作ってみました。 Dim yobidashikey As Int32 = 1 Dim cn As New OleDbConnection cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _ & "Data Source=C:\VB2005\KEYCHECK.mdb" Dim da As OleDbDataAdapter 'da = New OleDbDataAdapter("SELECT * FROM data WHERE key1 = 2", cn) da = New OleDbDataAdapter("SELECT * FROM data WHERE key1 = '" & yobidashikey & "'", cn) Dim ds As New DataSet da.Fill(ds, "data") DataGridView1.DataSource = ds.Tables("data") コメントアウトしてある直接「2」を指定した時は、デ-タグリッドビュ-にオ-トナンバが2の行が表示できました。 次に、yobidashikeyにオ-トナンバの値を入れて動作させると、da.Fill(ds, "data")で「抽出条件でデータ型が一致しません。」のエラ-が出てしまいました。 ちなみに、Dim yobidashikey As Int32 としたのは、DRead.GetFieldType(i).ToString()でオ-トナンバの項目がInt32と 表示されたので、この型にしました。 実際にオ-トナンバをキイ-にして読み込むシステムを作りたいので、是非教えて頂きたいと思います。 よろしくお願いします。

  • デ-タテ-ブルの内容での更新の書き方が分らず困っています

    VB2008とADO.NETを勉強中の初心者です。 以下のようなプログラムで、デ-タテ-ブルの内容を変更後(このプログラムでは削除のみですが、追加の処理もやりたいと思っています)"SYOYOURYOU"を更新して、再度読み込みたいと思っています。 いろいろ、参考書等を見たのですが旨く処理できません。 *DBを再読み込みのために更新* の部分での記述の方法を教えて頂けないでしょうか。 よろしくお願いします。 '*LLCの初期化 Dim LLC As Integer = 0 Dim cn As New OleDbConnection cn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _ & "Data Source=C:\MAPICS\MAPICS-S.mdb" Dim da As OleDbDataAdapter 'DataAdapterの作成 '*LLCを 0 から 10 まで処理 For LLC = 0 To 10 '所要量抽出 'DataAdapterの作成 da = New OleDbDataAdapter("SELECT * FROM SYOYOURYOU WHERE Syo_LLC =" & Str(LLC), cn) 'データを取得 Dim ds As New DataSet da.Fill(ds, "SYOYOURYOU") If ds.Tables("SYOYOURYOU").Rows.Count > 0 Then 'DataGridViewに表示 DataGridView1.DataSource = ds.Tables("SYOYOURYOU") MsgBox("確認1") For i = 0 To ds.Tables("SYOYOURYOU").Rows.Count - 1 'SYOYOURYOUをもとに処理を行う(この部分は省略) '処理済みのSYOYOURYOUのデ-タを削除 Dim dr As DataRow dr = ds.Tables("SYOYOURYOU").Rows(i) dr.Delete() 'DataGridViewに表示 DataGridView1.DataSource = ds.Tables("SYOYOURYOU") MsgBox("確認1") Next '***************************** 'DBを再読み込みのために更新 '***************************** End If Next '終了処理 End

  • VB.netでJet.OLEDBを使いCSVを読み

    VB.netでOleDbConnectionを使ってCSVを読み込むと便利ですが、属性判定を勝手にされたくありません。 どうすればコントロールできますか? 個別に属性を決めるか、もしくは全部文字列として受け取りたいです。 何もしなければ、項目の属性が自動で決まりますが、その属性判断が甘く、属性に合わない値が消えます。 例えば、 日付項目っぽい値が入っている項目にたまに文字列がるとすると、 その項目が日付項目になって、日付項目に合わないデータは空白になってしまいます。 CSVの読み込みは一旦すべて文字列にして受け取り、その後の事はアプリでコントロールしたいです。 どうすればできますか? Dim OleDbConnection1 As New OleDb.OleDbConnection Dim OleDbCommand1 As New OleDb.OleDbCommand Dim OleDbDataAdapter1 As New OleDb.OleDbDataAdapter Dim FileInfo1 As New FileInfo(CSVファイルの名前をフルパスで) OleDbConnection1.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _ & "Data Source=" & FileInfo1.DirectoryName & "\;" _ & "Extended Properties=" & ControlChars.Quote & "Text;HDR=No;FMT=Delimited" & ControlChars.Quote OleDbConnection1.Open() OleDbCommand1.CommandText = "SELECT * FROM [" & FileInfo1.Name & "]" OleDbCommand1.Connection = OleDbConnection1 OleDbDataAdapter1.SelectCommand = OleDbCommand1 OleDbDataAdapter1.Fill(DataTable1) OleDbDataAdapter1.Dispose() OleDbCommand1.Dispose() OleDbConnection1.Dispose()

  • 【VB】データグリッドに読み込んだテーブルの変更を元のデータベースに反映させたい

    VB歴6ヶ月です。 VBのバージョンは2005です。 mdbから読み込んだデータベースをデータグリッドビューコントロールで表示しました。 CNには接続パスが入っていてmdbとの接続は確立しています。 データグリッドビューコントロールのオブジェクト名はDGVです。 読み込むテーブル名はt社員マスターです。 Private sub メンテナンス() Dim DS As DataSet = New DataSet("社員マスター") Dim SQL As String = "SELECT * FROM t社員マスター" Dim DA As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(SQL, CN) DA.Fill(DS, "社員マスター") Dim DV As DataView = New DataView(DS.Tables("社員マスター")) DGV.DataSource = DV End sub これでグリッドに読み込ますことはできたのですが、 読み込んだデータをグリッド上で変更したら元のデータベースにも反映したいのですが やり方がわかりません >< 具体的なコード、やり方を教えていただけたらありがたいです。