none
TableAdapterのDeleteメソッドでオプティミスティック同時実行制御が効かない RRS feed

  • 質問


  • TableAdapterを使ってDBを更新するWebアプリケーションを作成していますが、
    TableAdapter.Delete()メソッドでオブティミスティック同時実行制御が働きません。

    DeleteのCommandTextには次のようなSQLを設定しています。
    DELETE FROM MyTable WHERE UpdateDate = @Original_UpdateDate AND ApplyDate = @Original_ApplyDate

    またDataSet.Designer.csファイル内に自動生成されたTableAdapterのDeleteメソッドの部分は以下のようになっております。

            [System.Diagnostics.DebuggerNonUserCodeAttribute()]
            [System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")]
            [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Delete, true)]
            public virtual int Delete(System.DateTime Original_UpdateDate, System.DateTime Original_ApplyDate) {
                this.Adapter.DeleteCommand.Parameters[0].Value = ((System.DateTime)(Original_UpdateDate));
                this.Adapter.DeleteCommand.Parameters[1].Value = ((System.DateTime)(Original_ApplyDate));
                System.Data.ConnectionState previousConnectionState = this.Adapter.DeleteCommand.Connection.State;
                if (((this.Adapter.DeleteCommand.Connection.State & System.Data.ConnectionState.Open)
                            != System.Data.ConnectionState.Open)) {
                    this.Adapter.DeleteCommand.Connection.Open();
                }
                try {
                    int returnValue = this.Adapter.DeleteCommand.ExecuteNonQuery();    // (※)
                    return returnValue;
                }
                finally {
                    if ((previousConnectionState == System.Data.ConnectionState.Closed)) {
                        this.Adapter.DeleteCommand.Connection.Close();
                    }
                }
            }


    デバッグしてみると上記コードの(※)のところでreturnValueは「0」が返ってきます。
    MSDNのDBConcurrencyExceptionクラスの説明(http://msdn2.microsoft.com/ja-jp/library/bsdf9tb2.aspx)によると、
    returnValueが0になるようなケースはDBConcurrencyException例外がthrowされるように
    読み取れますが、上記のコードでは例外はthrowされずに0を戻してきます。
    なぜこのような挙動になってしまうのか分かりません。

    ちなみにTableAdapter.Update()の方は期待通りDbConcurrencyException例外がthrowされています。

    ASP.NET / C# / Framework2.0

    2006年8月24日 9:40

すべての返信

  • SQL文をよく見てみましょう。
    対象とするデータがすでに変更されているときは、削除すべきデータを見つけられないような条件になってますよね。
    であれば、処理するデータが0件、であってませんか?

    Updateも同じだったように思うんだけど、例外がでてるのはなぜだろう。。。

     

    2006年8月24日 10:07

  • >対象とするデータがすでに変更されているときは、削除すべきデータを見つけられないような条件になってますよね。
    >であれば、処理するデータが0件、であってませんか?

    削除すべきデータが見つけられなかった(処理するデータが0件)ときに、
    DbConcurrencyException例外がthrowされると思っていたのですが、違うのでしょうか。

    2006年8月24日 10:28
  • System.Data.DataAdapter の Update メソッドでは更新や削除時にオプティミスティックロックによる例外 DbConcurrencyException が発生するようになっていますが、ウィザードが作成した Delete メソッドは、ソースの通り、単に処理件数を返すだけになっています。

    これはそういう仕様なんだと思います。
    Delete の戻り値を確認するか、Delete ではなく Update による削除を行うことになると思います。

    ちなみに、ウィザードが作成した HogeTableAdapter の Update メソッドの方は以下の仕様になっています。
    これは紛らわしくてミスの元になるような気がしました。

    HogeTableAdapter の Update メソッドには複数のオーバーロードがあり、DataTable 等を指定するものや主キーを指定するものがあります。主キーを指定するもの以外は元の Update メソッドが呼び出されるために DbConcurrencyException が発生しますが、主キーを指定する Update メソッドでは Delete メソッドと同様に処理件数が返されるだけになっています。

    2006年8月24日 11:21

  • > これはそういう仕様なんだと思います。
    > Delete の戻り値を確認するか、Delete ではなく Update による削除を行うことになると思います。

    私もそのように感じました。
    そのような仕様であれば仕方ないですね。

    しかし、Updateメソッドの方は紛らわしいですね。

    もしかして主キーを指定するタイプのメソッドはDataSourceコントロールとの連携の関係で
    (DbConcurrencyExceptionをthrowではなく)戻り値で返すようになっているのかな。。。

    2006年8月25日 1:06