- PR -

DataSetへの追加・更新ができない。

投稿者投稿内容
とも
会議室デビュー日: 2005/11/17
投稿数: 5
投稿日時: 2005-11-17 22:06
はじめまして。ともと申します。
いつも閲覧させていただいていますが、今回はどうしても解決できないので
ご質問させていただきます。
初心者のため、見苦しいところもあると思いますが、
どうか、ご教授お願いいたします。

[開発言語]
VB.NET 2003 + ADO.NET
[データベース構造]
テーブル名:name
列:
id(整数型,主キー),name(テキスト型)

ADO.NETを使ってアクセスのデータベースを更新したく、
下記のようなプログラムを作成しました。
ところが、データは取得できますが、更新しても結果が反映されません。
Update,Insert,Deleteでも同じように更新できません。
SQL文はアクセス上で実行し動作を確認してから、使用するようにしています。
SQL文を用いて、データベースを更新するには何か特別な方法が必要なのでしょうか?

備考:なんども確認しましたが、エラーは出てないようです。純粋にデータセット
に更新が反映されていないようです。


ボタンのクリックイベント
============================================================
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'コネクションオブジェクト
Dim oleCon As New OleDb.OleDbConnection
'データアダプター
Dim oleAdap As New OleDb.OleDbDataAdapter
'データセット
Dim oleDataset As New Data.DataSet
'テーブルの追加
oleDataset.Tables.Add("name")

'接続文字列
Dim dbPath As String = Application.StartupPath & "\test2.MDB"
oleCon.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & dbPath & ";"
Dim selectSql As String
Dim sql As String
selectSql = "select * from name;"
'SQL
sql = "UPDATE name set user_name='test';"

Dim i As Integer

Try
'コネクションを開く
oleCon.Open()

'セレクトコマンドを作成し実行
oleAdap.SelectCommand = New OleDb.OleDbCommand(selectSql, oleCon)
'データセットを更新
oleAdap.Fill(oleDataset, "name")

'コマンド生成
oleAdap.UpdateCommand = New OleDb.OleDbCommand(sql, oleCon)

'更新の確認
If (MessageBox.Show("更新しますか?", "確認", MessageBoxButtons.OKCancel) = DialogResult.OK) Then
'更新を反映(変更された行を表示)
Debug.WriteLine(oleAdap.Update(oleDataset, "name"))
oleDataset.AcceptChanges()
Else
'更新をロールバック
oleDataset.Tables("name").RejectChanges()
End If

'更新状況を出力
Debug.WriteLine("-----------")
For i = 0 To oleDataset.Tables("name").Rows.Count - 1
Debug.WriteLine(oleDataset.Tables("name").Rows(i).RowState.ToString)
Next
Debug.WriteLine("-----------")

'データグリッドへデータ表示
DataGrid1.DataSource = Nothing
DataGrid1.DataSource = oleDataset

Catch err As Exception
'エラー内容を表示
MessageBox.Show(err.Message & err.StackTrace)
Finally
'接続を閉じる
oleCon.Close()
End Try
End Sub
======================================================================
とも
会議室デビュー日: 2005/11/17
投稿数: 5
投稿日時: 2005-11-17 22:15
すみません。ソースが非常に見づらくなってしまいました。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2005-11-18 00:22
こんにちは。

「データセットへの更新」と「データベースへの更新」がごっちゃになっているからですね。

コード:
oleAdap.UpdateCommand = New OleDb.OleDbCommand(sql, oleCon)


この部分を
コード:
OleDbCommand command = new OleDbCommand(sql, oleCon);
command.ExecuteNonQuery();


としてみて下さい。(C#で申し訳ない。読みかえて下さい)
これで「データベースが更新」されます。
その後、最初に取得したようにデータセットに値を詰めて下さい。

とりあえずこれでOKですが…。

引用:

テーブル名:name
列:
id(整数型,主キー),name(テキスト型)



コード:
sql = "UPDATE name set user_name='test';"


列名が違いますね。(ただの掲示板への書き間違いですね?)

更に、
OleDbDataAdapter のヘルプを呼んで頂くと分かりますが、
「DataSet 内の挿入行、更新行、または削除行に対して、INSERT、UPDATE、または DELETE ステートメントを個別に呼び出します。」
です。
この辺は DataSet と DbDataAdapter の関係をもう少し調べてみてください。
少し言うと、「メモリ上にある DataSet に行った追加や更新や削除を、DbDataAdapter を使ってデータベースに反映させる」です。

_________________
囚人のジレンマな日々
とも
会議室デビュー日: 2005/11/17
投稿数: 5
投稿日時: 2005-11-18 01:03
囚人さん。解答ありがとうございます。

ご指摘いただいた部分修正しましたところ、更新ができました。

ですが、私の説明不足のため、申しわけないんですが、
今回私がしたかったのは、


・データセットへ何件かまとめて更新
・その結果をDBへ反映
・やり直す時やエラーが出たときはデータセットを
RejectChangesメソッドでロールバック。


ということを実現したいと考えています。

ExecuteNonQueryメソッドは、直接DBを更新するんですよね。
今回の仕様上件数が非常に多いことと、複数で接続することはないので、データセットを使いメモリ上で操作することにより、高速化を考えています。

再三ご質問させていただき、申しわけありませんが、
データセットへの更新方法も、教えていただければ幸いです。

何度も申しわけありません。

#
列名の件は私のミスです。申しわけありません。
あと、ソースではUpdateですが、Insert,Delete文を発行する時は
--
'コマンド生成
oleAdap.UpdateCommand
--
の部分をInsertCommand,DeleteCommandに変更してテストしています。

ほげた
ベテラン
会議室デビュー日: 2002/05/08
投稿数: 67
お住まい・勤務地: なごやん
投稿日時: 2005-11-18 01:59
DBを更新する場合、DataAdapter.Update() メソッドを使用します。

DataSetは非接続のまま逐次データ更新しておき、
必要に応じてUpdate()すればよいかと。
とも
会議室デビュー日: 2005/11/17
投稿数: 5
投稿日時: 2005-11-18 02:10
ほげたさん。解答ありがとうございます。

引用:

DataSetは非接続のまま逐次データ更新しておき、
必要に応じてUpdate()すればよいかと。



この部分は理解できるのですが、その前の段階のDataSetに更新処理(updateやinsertなど)をする方法がわからず悩んでいます。

私の調べたところでは
oleAdap.UpdateCommand = New OleDb.OleDbCommand(sql, oleCon)
のように、Adapter各種commandプロパティにセットした時点でデータセットが
更新されると認識しているのですが、違うのでしょうか?

#
訂正
'更新状況を出力




の場所が間違っていました。
メッセージボックスを出す前ですね。

それでも出力結果は「Unchanged」です。
何か根本的に間違っているのでしょうか・・・。

[ メッセージ編集済み 編集者: とも 編集日時 2005-11-18 02:12 ]
ほげた
ベテラン
会議室デビュー日: 2002/05/08
投稿数: 67
お住まい・勤務地: なごやん
投稿日時: 2005-11-18 03:21
最初のコードにある
 'データセットを更新

 '更新の確認
の間に DataSet を変更する処理が無いので、変更なしとなるのは当然です。

もしかして、DataSet に対する変更もクエリで行うと思っていませんか。
DataSet は単なるクラスであり、更新とは
DataTable.NewRow() や DataRow の変更を行うことです。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2005-11-18 09:49
ほげたさんも仰っていますが、DataSet に対する操作をクエリーで行おうとしているのでは?
引用:

それでも出力結果は「Unchanged」です。


これがヒントですね。
DataTable に「メモリ上で」データを追加したり、更新したり、削除したりすると、RowState が「追加状態」「更新状態」「削除状態」となります。
その状態で DbDataAdapter の Update() を呼び出すと、各 RowState 状態に応じて「InsertCommand」「UpdateCommand」「DeleteCommand」が呼び出されて、データベースが更新される、という事です。

_________________
囚人のジレンマな日々

スキルアップ/キャリアアップ(JOB@IT)