[PRB] 変更されたコマンドがCommandBuilder によって元に戻される

文書翻訳 文書翻訳
文書番号: 310366 - 対象製品
この記事は、以前は次の ID で公開されていました: JP310366
この資料は、アーカイブされました。これは "現状のまま" で提供され、更新されることはありません。
すべて展開する | すべて折りたたむ

目次

現象

CommandBuilder オブジェクトが、次の DataAdapter.Update メソッドの呼び出しの際に変更しようとしているコマンドを再作成し、コマンドへの変更が失われる場合があります。この問題は、以下のような状況で発生します。
  • CommandBuilder オブジェクトを DataAdapter オブジェクトに関連付けた場合
  • CommandBuilder オブジェクトの GetInsertCommand、GetUpdateCommand、または GetDeleteCommand メソッドを使用して、コマンドを DataAdapter に明示的に割り当てた場合
  • CommandBuilder が生成するコマンドの 1 つを修正した場合
DataAdapter の Update メソッドを呼び出そうとすると、次のエラー メッセージが表示される場合があります。
'System.Data.SqlClient.SqlException' のハンドルされていない例外が system.data.dll で発生しました。

原因

この問題は、CommandBuilder が、生成したコマンドを動的に変更して元のコマンドに戻すために発生します。

解決方法

この問題を解決するには、以下のいずれかの方法を使用します。
  • CommandBuilder が生成するコマンドを修正しないようにします。自分で作成した Command オブジェクトは、CommandBuilder によって変更されません。
  • InsertCommand、DeleteCommand、または UpdateCommand オブジェクトを、新しい DataAdapter にコピーします (「詳細」の例を参照してください)。新しい DataAdapter 変数は、古い DataAdapter 変数と同じまたは狭いスコープを持つ必要があります。
  • CommandBuilder を使用しないようにします。独自の Command オブジェクトを作成するか、または Visual データ ツールを使用して記述します。

状況

この現象は仕様によるものです。

詳細

問題の再現手順

  1. 新しい Visual Basic Windows アプリケーション プロジェクトを作成します。Form1 がデフォルトでプロジェクトに追加されています。
  2. フォームをダブルクリックし、コード ウィンドウの先頭に以下のコードを追加します。
    Imports System.Data.SqlClient
    
  3. Button コントロールを Form1 に追加します。
  4. ボタンをダブルクリックし、クリック イベントに以下のコードを追加します。
    Dim cn As New SqlConnection()
    Dim custDS As New DataSet()
    Dim da1 As New SqlDataAdapter()
    Dim da2 As New SqlDataAdapter()
    Dim dr As DataRow
    Dim cb As SqlCommandBuilder
    
    cn.ConnectionString = "server=servername;database=northwind;uid=sa;pwd=password;"
    cn.Open()
    da1 = New SqlDataAdapter("select * from Customers", cn)
    cb = New SqlCommandBuilder(da1)
    
    da1.Fill(custDS, "Customers")
    
    '元のコマンドを取得します。
    
    da1.InsertCommand = cb.GetInsertCommand
    da1.DeleteCommand = cb.GetDeleteCommand
    da1.UpdateCommand = cb.GetUpdateCommand
    
    Debug.WriteLine("Original command length: " & da1.InsertCommand.CommandText.Length)
    
    'Insert コマンドを変更します。
    
    da1.InsertCommand.CommandText = "select * from customers where customerid=@@identity"
    
    da1.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord
    
    da2.InsertCommand = da1.InsertCommand
    da2.DeleteCommand = da1.DeleteCommand
    da2.UpdateCommand = da1.UpdateCommand
    
    'テーブルにレコードを追加します。
    
    Dim tblCust As DataTable
    tblCust = custDS.Tables("Customers")
    
    Dim drCust As DataRow
    
    drCust = tblCust.NewRow()
    drCust("CustomerID") = "ZYYYY"
    drCust("CompanyName") = "Zora's Yummies"
    drCust("ContactName") = "Christophe Namby"
    drCust("ContactTitle") = "Assistant Manager"
    
    tblCust.Rows.Add(drCust)
    
    'バックエンドを更新します。
    
    Debug.WriteLine("Length da1 before insert: " & da1.InsertCommand.CommandText.Length)
    
    da1.Update(custDS, "Customers")
    
    Debug.WriteLine("Length da1 after insert: " & da1.InsertCommand.CommandText.Length)
    Debug.WriteLine("length da2 before insert: " & da2.InsertCommand.CommandText.Length)
    
    da2.Update(custDS, "Customers")
    
    Debug.WriteLine("Length da2 after insert: " & da2.InsertCommand.CommandText.Length)
    
  5. 使用している Microsoft SQL Server に接続されるように、接続文字列を修正します。
  6. F5 キーを押してコードを実行します。
  7. この問題を解決するには、以下の行をコメントにします。
    da1.Update(custDS, "Customers")
    
この方法で問題が解決される理由は、CommandBuilder がコマンドを生成するタイミングを知るために DataAdapter ("da1") 上の RowUpdating イベントをフックするためです。別の DataAdapter ("da2") にコマンドをコピーすると、CommandBuilder はイベントにフックされなくなり、コマンドは変更されません。

変数のスコープ (有効範囲) は重要です。"da1" および SqlCommandBuilder ("cb") がスコープから外れ、ガーベジ コレクションが発生すると、CommandBuilder がコマンドを Nothing (Visual C# では null) に設定します。このため、これらのコマンドを "da2" で使用できなくなります。ガーベジ コレクションはランダムに発生するため、da2.Update メソッド呼び出しによって断続的に NullReferenceException エラーが発生する場合があります。

関連情報

この資料は米国 Microsoft Corporation から提供されている Knowledge Base の Article ID 310366 (最終更新日 2002-01-15) をもとに作成したものです。

この資料に含まれているサンプル コード/プログラムは英語版を前提に書かれたものをありのままに記述しており、日本語環境での動作は確認されておりません。

プロパティ

文書番号: 310366 - 最終更新日: 2014年2月24日 - リビジョン: 1.0
この資料は以下の製品について記述したものです。
  • Microsoft ADO .NET (included with the .NET Framework)
  • Microsoft Visual Basic .NET 2002 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
キーワード:?
kbnosurvey kbarchive kbprb kbadonet KB310366
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com