- - PR -
DataAdapterの自動更新機能がうまくいかない。
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2007-03-07 11:52
はじめまして。
現在、VisualStudio2003を使用して、件名の通りDataAdapterの自動更新を行おうと考えています。 しかし、UPDATEコマンドを発行したときに、下記エラーが発生します。 ■エラー System.InvalidOperationException: UpdateCommand の動的SQL生成は、キーである列情報を返さないSelectCommandに対してサポートされていません。 selectコマンドではキーを含む動的SQLを発行しているのにもかかわらず上記のエラーが発生します。 以下、コードの詳細です。 Dim dsTable As New DataTable Dim dsWbsData As New DataSet Dim dsAdapter As New OleDbDataAdapter #Region "データセット処理" '********************************************************************** ' [名称] ' データセット処理 ' [概要] ' データグリッド内にデータをSETする。 ' [引数] ' strCode :Stringパラメータ ' strSyainCode :Stringパラメータ ' [戻り値] ' なし ' [備考] ' − '********************************************************************** Public Sub SetData(ByVal strCode As String, ByVal strSyainCode As String) Dim commandBuilder As OleDbCommandBuilder ' データグリッド内のデータ初期化 dsTable.Clear() ' データセット初期化 dsWbsData.Clear() ' WHERE句初期化 strWhereLine = Nothing ' WHERE句取得 GetWhereLine(strCode, strSyainCode) ' SelectCommand初期化 dsAdapter.SelectCommand = New OleDbCommand( _ " SELECT SIRYOYM," _ ←キー項目1 & " DATASBT," _ & " DATAKNRNO_SC," _ ←キー項目2 & " DATAKNRGY_SC," _ ←キー項目3 & " D_KADOUYM, " _ & " D_JUGYOINCD," _ & " D_WBSCD, " _ & " D_SAGYOUKOUTEI," _ & " D_SAGYOUKBN," _ & " D_BUMONCD," _ & " D_KADOUYMD," _ & " D_KADOUHOUR," _ & " D_GENCCD, " _ & " D_KTDTYP," _ & " D_KOUSUKBN, " _ & " D_PRJSBT," _ & " D_WBSSBT, " _ & " D_GENCCATE," _ & " DENNO_SC," _ & " DENGY_SC," _ & " TMSTYMD," _ & " TMSTTIME" _ & " FROM NT_KADMSI " & strWhereLine _ & " ORDER BY D_JUGYOINCD, D_KADOUYMD, D_WBSCD", oConn) ' SELECT文の結果取得 ' SelectCommandの結果をDataSetに設定() dsAdapter.Fill(dsWbsData, "データ") ' データバインド DataGrid1.SetDataBinding(dsWbsData, "データ") End Sub #End Region #Region "更新ボタン押下時ハンドル処理" '********************************************************************** ' [名称] ' 更新ボタン押下時ハンドル処理 ' [概要] ' データグリッド上の更新および追加・削除されたデータをデータベースに ' 反映する。 ' [引数] ' sender : ハンドルオブジェクト ' e : イベントパラメータ ' [戻り値] ' なし ' [備考] ' − '********************************************************************** Private Sub btnUpdate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnUpdate.Click Dim intCurIdx As Integer Dim retValue As Integer Dim sqlCB As OleDbCommandBuilder Try sqlCB = New OleDbCommandBuilder(dsAdapter) ' dsWbsDataが保持する情報を元に変更された個所についてDBを更新 retValue = dsAdapter.Update(dsWbsData, "当月分日報データ") MessageBox.Show("正常にデータ更新されました。", "お知らせ") Catch ex As Exception 'データの更新で発生したエラーを捕捉する MessageBox.Show("データの更新に失敗しました。" _ + vbCrLf + ex.ToString) End Try End Sub #End Region | ||||
|
投稿日時: 2007-03-07 11:59
少し修正です。
#Region "更新ボタン押下時ハンドル処理" '********************************************************************** ' [名称] ' 更新ボタン押下時ハンドル処理 ' [概要] ' データグリッド上の更新および追加・削除されたデータをデータベースに ' 反映する。 ' [引数] ' sender : ハンドルオブジェクト ' e : イベントパラメータ ' [戻り値] ' なし ' [備考] ' − '********************************************************************** Private Sub btnUpdate_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnUpdate.Click Dim intCurIdx As Integer Dim retValue As Integer Dim sqlCB As OleDbCommandBuilder Try sqlCB = New OleDbCommandBuilder(dsAdapter) ' dsWbsDataが保持する情報を元に変更された個所についてDBを更新 retValue = dsAdapter.Update(dsWbsData, "当月分日報データ") MessageBox.Show("正常にデータ更新されました。", "お知らせ") Catch ex As Exception 'データの更新で発生したエラーを捕捉する MessageBox.Show("データの更新に失敗しました。" _ + vbCrLf + ex.ToString) End Try End Sub #End Region | ||||
|
投稿日時: 2007-03-07 12:14
主キーがないだけじゃないの?
| ||||
|
投稿日時: 2007-03-07 15:38
返信ありがとうございます。
テーブルのキーは↑に書いた通り3つの項目について有効です。 | ||||
|
投稿日時: 2007-03-07 15:54
DataSet上で主キーがないんですよ。
例えば、Fillの前に dsAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey; を追加するとか。 | ||||
|
投稿日時: 2007-03-07 16:37
返信ありがとうございます。
>dsAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey 上記のコードを追加してみましたが、やはり同じエラーが発生します。 もう少し調べてみます。 | ||||
|
投稿日時: 2007-03-07 17:38
こんなヘルプを見つけました。
↓ こいつが原因なんでしょうか? ******************************************************************************** AddWithKey 必要な列と主キー情報を追加してスキーマを完成します。主キー情報を DataTable に追加する方法の詳細については、「FillSchema」を参照して ください。.NET Framework OLE DB 用データ プロバイダで AddWithKey が 正しく機能するためには、ネイティブな OLE DB プロバイダが DBPROP_UNIQUEROWS プロパティを設定して必要な主キー情報を取得し、 IColumnsRowset 内の DBCOLUMN_KEYCOLUMN を調べてどの列が主キー列かを確 認する必要があります。DataTable ごとに主キー制約を明示的に設定するこ ともできます。これにより、既存のレコードと一致する入力レコードが、追 加ではなく更新されるようになります。 ******************************************************************************** | ||||
|
投稿日時: 2007-03-08 19:01
原因は私もわからないのですが、調べる方向が間違ってそうなので書いておきます。
「UpdateCommand の動的SQL生成」のエラーとのことですので、 DataSet上の主キーとかは関係ないと思います。 極端な話、DataSetもDataTableも使わなくても同じエラーは出せます。 DataAdapterを生成してSelectCommandを設定して、 コマンドビルダーを生成して、そのGetUpdateCommandメソッドを呼んでみたら 同じエラーが返ってくると思います。 例えば以下のような感じで。
DataSetのUpdateのタイミングで出るのは、Updateのときに内部的に DbCommandBuilderから更新用のコマンドを取得するからです。 要するにSELECT文に対応するUPDATE, DELETE, INSERTコマンドを 自動生成するのに失敗しているものと思われます。 その原因は、SELECT文には一意な列が含まれていないということのようです。 上記のDebug.Printのところでエラーがでないようになれば解決すると思いますので、 調査を進めるならSQL文を単一列の主キーを持つテーブルから無条件で取得するだけのSQLに書き換えてみるとか、 そういうところから始めてみてはどうでしょうか? あと、OLEDBを使われているようですが、DBMSは何でしょうか? |