- - PR -
.net 同時実行違反
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2003-12-11 21:54
Ultra Web Grid を使用して、DBを更新しようとしています。
グリッドで変更された行だけを取得して、DataSetに格納して、 そのDataSetをOleDbDataAdapterに渡して更新しようとしています。 しかし、更新時にExceptionが発生し、「同時実行違反」になってしまいます。 「更新された行の取得時にRowStateをModifiedにするために、一旦ダミーの値を入れ、AcceptChanges()した後に、本当の値を入れる」という特殊なことをしていますが、それが邪魔をしているのでしょうか。 グリッド変更時のイベントのコード private void Uwg_UpdateCell(object sender, Infragistics.WebUI.UltraWebGrid.CellEventArgs e) { DataSet ds = (DataSet)ViewState[DISP_DATA_KEY]; //データセットを取得 DataRow row=null; DataTable table=null; object key=e.Cell.Row.Cells.FromKey(Uwg.Bands[0].DataKeyField).ToString(); //行のキーの値を取得 table=ds.Tables[e.Cell.Band.BaseTableName]; //データソーステーブル取得 if (key!=null) row=table.Rows.Find(key); //キー項目取得 if (row == null) { //キーで項目がないとき新たに行作成 row = table.NewRow(); row[table.PrimaryKey[0].ColumnName] = key.ToString(); table.Rows.Add(row); // key=e.Cell.Row.Cells.FromKey(Uwg.Bands[0].DataKeyField).ToString(); //行のキーの値を取得 for (int i=0; i<table.Columns.Count; i++) { row[i] = e.Cell.Row.Cells[i].Value; } row[e.Cell.Column.Index]="$"; //ダミー文字 row.AcceptChanges(); } updateDataSet(e, ref ds); //セルの値設定 ViewState[DISP_DATA_KEY] = ds; //データセットをhideで持つ } private void updateDataSet(CellEventArgs e, ref DataSet pDs) { DataRow row=null; DataTable table=null; object key=e.Cell.Row.Cells.FromKey(Uwg.Bands[0].DataKeyField).ToString(); //行のキーの値を取得 table=pDs.Tables[e.Cell.Band.BaseTableName]; //データソーステーブル取得 if (key!=null) row=table.Rows.Find(key); //キー項目取得 if(row!=null) row[e.Cell.Column.Index]=e.Cell.Value; //テーブル行に設定 } で行を設定しています。 更新は db.oleDbCon.Open(); //コネクションを開く int retVal = oleAdap.Fill(ds); //検索する で更新しています。 更新時にExceptionが発生し、「同時実行違反 : UpdateCommand によって 0 件処理されました。」といわれてしまいます。 原因がわかりません。 わかる方がいれば教えてください。 | ||||
|
投稿日時: 2003-12-12 18:37
AcceptChangeを実行した時点で、DataSet上ではダミーのデータが
もともと存在しているデータだと思い込んでしまうのでは? DataSetで更新する場合、DataSetが持っているもともとのデータと 現在のDB上のデータと比較することで同時実行違反かどうかの 判定を行っていると思う。 このため、上記のようにダミーのデータがもともとのデータだと 思い込ませるような特殊なことをやっていたら、同時実行違反と みなされて当然のよーな。 違うかな? | ||||
|
投稿日時: 2003-12-15 10:48
確かにそれっぽい動きはしますね。
ということはRowStateを変更して、DataSetでテーブルを更新しようとすると、 変更前の値を持っておかないといけないということですね。 変更前の値を持たずにうまくRowStateを変更する方法はないのでしょうか? また、変更前の値を持たず、変更分のDataSetだけでUpdateメソッドを使用してテーブルを更新する方法はないのでしょうか? わかる方がいらっしゃれば、教えてください。 | ||||
|
投稿日時: 2003-12-15 12:04
質問の意図がよくわからないのですが。
UltraWebGridでも、それ単体でデータは持っていないのではないでしょうか。体験版をダウンロードして、かなり以前に消してしまいましたが、DataSetを参照させていたと思います。つまり、元のDataSetを参照として持っている以上、それはViewStateにも入っており、UltraWebGridの何らかのプロパティを参照すれば、元のDataSetが取り出せたと思います。そこに、「元の値」が入っているDataRowがあるのだから、それを利用すればいいのでは? #使わないと決めた理由は、DataSetがそのままViewStateに入って #ページが非常に重くなるから、だったと思う。 #DataGridと比較して非常に重たかった、のは確実。 あと、ソースをそのまま掲載するより、流れにまとめてくださるとありがたいです。読んで理解する時間をかけなくてすみますから。また、この手の問題は、SQL文をどのように組み立てているかも問題になります。自動生成しているのか、開発者が生成しているのか。可能な範囲で掲載してください。 | ||||
|
投稿日時: 2003-12-15 17:52
わかりにくくてすみません。
やっていること---------- ページロードで、UltraWebGridで表示させるデータを取得し、 DataSourceプロパティに入れて、DataBindさせています。 UpdateCellイベントでDataSetの内容を変更し、 更新ボタンのイベントでDataSetを使用して、テーブルを更新しています。 --------------------- UltraWebGridで表示させているDataSetを取り出せるのですか? UpdateCellイベントでUltraWebGridのDataSourceを参照するとNullになってしまいます。 UltraWebGridのデータをDataSetで取得できそうなプロパティやメソッドが見当たらなかったので、自分で対象データをViewStateに格納しようと思い、変更されたデータだけDataSetで格納したかったのです。 UltraWebGridがずっとDataSetを持っていて、その参照しているDataSetを取り出せるのであれば、その方法を教えていただきたい。 自分の調査が足りないのか、見当たりませんでした。 また、更新の方法は「OleDbCommandBuilder」クラスを使用して、SQLを自動作成し、「OleDbDataAdapter」の「Update」メソッドで更新しています。 更新部分のソース---------------- OleDbCommandBuilder cb = new OleDbCommandBuilder(oleAdap); //更新用SQL作成 int kensu = oleAdap.Update(pDs); //DB更新 ------------------------------- わかる方がいれば、お願いします。 | ||||
|
投稿日時: 2003-12-15 18:17
UltraWebGridは消してしまったのでDataGridで見ると・・・あ、Nothingだ。失礼しました。
CommandBuilderから関連するリンクをたどっていくと書いてあるのですが、CommandBuiiderが作るUpdate文、Delete文は、「オプティミスティック同時実行制御」といって、全ての列のデータが一致していなければなりません。つまり、 ID, DATA1, DATA2 ---------------- 1, aaaa1, bbbb1 というデータを、 1, cccc1, dddd1 に変更しようとすると、次のようなUPDATE文が作成されます。 UPDATE table1 SET ID=1, DATA1='cccc1', DATA2='dddd1' WHERE ID=1 AND DATA1='aaaa1' AND DATA2='bbbb1' つまり、ここででている「同時実行」は、「同じSQL文で二回書き換えようとしている」とかの意味ではなく、「あなたが書き換えようとしてから、他の誰かが書き換えています」という、「人」系の同時実行です。 DataViewにしまって、そこから取り出したDataTableに対して変更をかけるのでしたら、わざわざダミー値をいれる必要はないのでは? または、Update文、Delete文を提供すれば(CommandBuilderを使わなければ)解決すると思います。(たぶんInsertと3つとも提供してやる必要があると思う) | ||||
|
投稿日時: 2003-12-15 18:46
UltraWebGridがただでさえ遅い上に、DataSetを全件ViewStateに持つと
件数が500件程度で動きがかなり遅くなってしまいます。 そこで、変更した行だけDataSetとしてViewStateに入れたい。 それで、変更前のデータを持とうと思わなかったので、ダミーを使用したのですが・・・ CommandBuilderクラスでご返信いただいたようなSQLを作成されてしまうと確かに駄目ですね。 SQLをこちらで書くしかないのでしょうか。 | ||||
|
投稿日時: 2003-12-15 21:57
変更した行をViewSetに入れる、というのが、ちょっと。変更を検知した時点でデータベースに反映するのはNGということですね。また、ViewState以外にSessionというのもありますが、これもNG?
そのほか、UltraWebGridの使用/仕様に関しては、GrapeCityに直接尋ねる方が早いと思います。 CommandBuilderに関しては、MSDN内にも記述があったと思うのですが、使わない方が吉です。また、アテにしすぎると凶です。 |
1