CommandBuilder でのコマンドの生成Generating Commands with CommandBuilders

SelectCommand プロパティが実行時に動的に指定される場合、たとえばクエリ ツールを使用してユーザーの記述したクエリ構文を解釈する場合は、適切な InsertCommandUpdateCommand、または DeleteCommand をデザイン時に指定することはできません。When the SelectCommand property is dynamically specified at run time, such as through a query tool that takes a textual command from the user, you may not be able to specify the appropriate InsertCommand, UpdateCommand, or DeleteCommand at design time. DataTable を単一データベース テーブルに割り当てたり、単一データベースから生成する場合は、DbCommandBuilder オブジェクトを利用して自動的に DeleteCommandInsertCommandUpdateCommand、および DbDataAdapter を生成できます。If your DataTable maps to or is generated from a single database table, you can take advantage of the DbCommandBuilder object to automatically generate the DeleteCommand, InsertCommand, and UpdateCommand of the DbDataAdapter.

コマンドを自動的に生成するための最低限の条件として、SelectCommand プロパティを設定する必要があります。As a minimum requirement, you must set the SelectCommand property in order for automatic command generation to work. SelectCommand プロパティで取得したテーブル スキーマによって、自動的に生成される INSERT、UPDATE、DELETE の各ステートメントの構文が決定されます。The table schema retrieved by the SelectCommand property determines the syntax of the automatically generated INSERT, UPDATE, and DELETE statements.

DbCommandBuilder は、INSERT、UPDATE、DELETE の各コマンドを生成するために SelectCommand を実行する必要があります。The DbCommandBuilder must execute the SelectCommand in order to return the metadata necessary to construct the INSERT, UPDATE, and DELETE SQL commands. その結果、データ ソースへの追加のトリップが必要になるため、パフォーマンスが低下する可能性があります。As a result, an extra trip to the data source is necessary, and this can hinder performance. 最適のパフォーマンスを実現するには、明示的にコマンドを指定し、DbCommandBuilder を使用しないようにします。To achieve optimal performance, specify your commands explicitly rather than using the DbCommandBuilder.

SelectCommand は少なくとも 1 つの主キーまたは一意の列を返す必要があります。The SelectCommand must also return at least one primary key or unique column. どちらも存在しない場合は、InvalidOperation 例外が生成され、コマンドは生成されません。If none are present, an InvalidOperation exception is generated, and the commands are not generated.

DataAdapter との関連付けが行われていて、DbCommandBuilderInsertCommandUpdateCommandDeleteCommand の各プロパティが null 参照である場合、DataAdapter は自動的にこれらのプロパティを生成します。When associated with a DataAdapter, the DbCommandBuilder automatically generates the InsertCommand, UpdateCommand, and DeleteCommand properties of the DataAdapter if they are null references. プロパティに対して既に Command が存在する場合は、既存の Command が使用されます。If a Command already exists for a property, the existing Command is used.

複数のテーブルを結合して作成したデータベース ビューは、単一データベース テーブルとは見なされません。Database views that are created by joining two or more tables together are not considered a single database table. この場合は、DbCommandBuilder を使用してコマンドを自動的に生成できないため、コマンドを明示的に指定する必要があります。In this instance you cannot use the DbCommandBuilder to automatically generate commands; you must specify your commands explicitly. データソースへの更新DataSetを解決するコマンドを明示的に設定する方法については、「 dataadapter を使用したデータソースの更新」を参照してください。For information about explicitly setting commands to resolve updates to a DataSet back to the data source, see Updating Data Sources with DataAdapters.

出力パラメーターを DataSet の更新行に割り当てることが必要な場合があります。You might want to map output parameters back to the updated row of a DataSet. 一般的なタスクの 1 つは、データ ソースの自動的に生成された ID フィールドまたはタイムスタンプの値を取得することです。One common task would be retrieving the value of an automatically generated identity field or time stamp from the data source. DbCommandBuilder は、既定では更新行の列に出力パラメーターを割り当てません。The DbCommandBuilder will not map output parameters to columns in an updated row by default. その場合は、コマンドを明示的に指定する必要があります。In this instance you must specify your command explicitly. 自動的に生成された id フィールドを、挿入された行の列にマップする例については、「 id またはオートナンバー値の取得」を参照してください。For an example of mapping an automatically generated identity field back to a column of an inserted row, see Retrieving Identity or Autonumber Values.

コマンドの自動生成規則Rules for Automatically Generated Commands

コマンドの自動生成規則を次の表に示します。The following table shows the rules for how automatically generated commands are generated.

コマンドCommand 規則Rule
InsertCommand RowStateAdded に設定されているテーブル内のすべての行に対して、データ ソースの行を挿入します。Inserts a row at the data source for all rows in the table with a RowState of Added. 更新可能なすべての列に対して値を挿入します (ただし、ID、式、タイムスタンプなどの列は除きます)。Inserts values for all columns that are updateable (but not columns such as identities, expressions, or timestamps).
UpdateCommand RowStateModified に設定されているテーブル内のすべての行に対して、データ ソースの行を更新します。Updates rows at the data source for all rows in the table with a RowState of Modified. ID や式などの更新不可能な列を除く、すべての列の値を更新します。Updates the values of all columns except for columns that are not updateable, such as identities or expressions. データ ソースの列の値と該当行の主キー列の値が一致し、さらにデータ ソースのその他の列がその行の元の値と一致する、すべての行を更新します。Updates all rows where the column values at the data source match the primary key column values of the row, and where the remaining columns at the data source match the original values of the row. 詳細については、このトピックで後述する「更新および削除のオプティミスティック同時実行制御」を参照してください。For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.
DeleteCommand RowStateDeleted に設定されているテーブル内のすべての行に対して、データ ソースの行を削除します。Deletes rows at the data source for all rows in the table with a RowState of Deleted. 列の値とその行の主キー列の値が一致し、さらにデータ ソースのその他の列がその行の元の値と一致する、すべての行を削除します。Deletes all rows where the column values match the primary key column values of the row, and where the remaining columns at the data source match the original values of the row. 詳細については、このトピックで後述する「更新および削除のオプティミスティック同時実行制御」を参照してください。For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.

更新および削除のオプティミスティック コンカレンシーOptimistic Concurrency Model for Updates and Deletes

UPDATE ステートメントと DELETE ステートメントに対してコマンドを自動的に生成するロジックは、オプティミスティック同時実行制御に基づいています。つまり、レコードは編集のためにロックされず、他のユーザーやプロセスによっていつでも変更できます。The logic for generating commands automatically for UPDATE and DELETE statements is based on optimistic concurrency--that is, records are not locked for editing and can be modified by other users or processes at any time. レコードは SELECT ステートメントによって返された後、UPDATE ステートメントまたは DELETE ステートメントの実行前に変更されている可能性もあるため、自動的に生成される UPDATE ステートメントまたは DELETE ステートメントには、元のすべての値を含み、データ ソースから削除されていない行だけを更新するように指定した WHERE 句が含まれます。Because a record could have been modified after it was returned from the SELECT statement, but before the UPDATE or DELETE statement is issued, the automatically generated UPDATE or DELETE statement contains a WHERE clause, specifying that a row is only updated if it contains all original values and has not been deleted from the data source. これにより、新しいデータが上書きされるのを防ぎます。This is done to avoid overwriting new data. 自動的に生成された更新コマンドが削除済みの行、または DataSet にある元の値が含まれていない行を更新しようとすると、コマンドはどのレコードにも反映されずに、DBConcurrencyException がスローされます。Where an automatically generated update attempts to update a row that has been deleted or that does not contain the original values found in the DataSet, the command does not affect any records, and a DBConcurrencyException is thrown.

元の値とは関係なく UPDATE または DELETE を実行する場合は、UpdateCommand に明示的に DataAdapter を設定し、コマンドの自動生成は行わないでください。If you want the UPDATE or DELETE to complete regardless of original values, you must explicitly set the UpdateCommand for the DataAdapter and not rely on automatic command generation.

コマンドの自動生成ロジックの制限事項Limitations of Automatic Command Generation Logic

コマンドの自動生成には次の制限事項が適用されます。The following limitations apply to automatic command generation.

リレーションシップのないテーブルに限定Unrelated Tables Only

コマンドの自動生成ロジックでは、データ ソースの他のテーブルへのリレーションシップを考慮せずに、独立したテーブルを対象として INSERT、UPDATE、または DELETE の各ステートメントを生成します。The automatic command generation logic generates INSERT, UPDATE, or DELETE statements for stand-alone tables without taking into account any relationships to other tables at the data source. その結果、Update を呼び出してデータベースの外部キー制約に関係する列に対する変更を発行すると、エラーが発生する場合があります。As a result, you may encounter a failure when calling Update to submit changes for a column that participates in a foreign key constraint in the database. このような例外を防ぐには、外部キー制約に関係する列の更新には DbCommandBuilder を使用せず、更新操作を実行するステートメントを明示的に指定します。To avoid this exception, do not use the DbCommandBuilder for updating columns involved in a foreign key constraint; instead, explicitly specify the statements used to perform the operation.

テーブル名と列名Table and Column Names

列名またはテーブル名にスペース、ピリオド (.)、疑問符 (?)、引用符、その他の英数字以外の特殊文字が含まれていると、それらの文字が角かっこで囲まれていても、コマンドの自動生成ロジックはエラーになる場合があります。Automatic command generation logic may fail if column names or table names contain any special characters, such as spaces, periods, quotation marks, or other nonalphanumeric characters, even if delimited by brackets. プロバイダーによって異なりますが、QuotePrefix パラメーターと QuoteSuffix パラメーターを設定すると、生成ロジックではスペースを処理できる場合があっても、特殊文字をエスケープできません。Depending on the provider, setting the QuotePrefix and QuoteSuffix parameters may allow the generation logic to process spaces, but it cannot escape special characters. スキーマの形式での完全修飾テーブル名がサポートされています。Fully qualified table names in the form of catalog.schema.table are supported.

CommandBuilder による SQL ステートメントの自動生成Using the CommandBuilder to Automatically Generate an SQL Statement

DataAdapter に対して SQL ステートメントを自動的に生成するには、まず SelectCommandDataAdapter プロパティを設定します。次に、CommandBuilder オブジェクトを作成し、DataAdapter で SQL ステートメントを自動的に生成する CommandBuilder を引数として指定します。To automatically generate SQL statements for a DataAdapter, first set the SelectCommand property of the DataAdapter, then create a CommandBuilder object, and specify as an argument the DataAdapter for which the CommandBuilder will automatically generate SQL statements.

' Assumes that connection is a valid SqlConnection object   
' inside of a Using block.  
Dim adapter As SqlDataAdapter = New SqlDataAdapter( _  
  "SELECT * FROM dbo.Customers", connection)  
Dim builder As SqlCommandBuilder = New SqlCommandBuilder(adapter)  
builder.QuotePrefix = "["  
builder.QuoteSuffix = "]"  
// Assumes that connection is a valid SqlConnection object  
// inside of a using block.  
SqlDataAdapter adapter = new SqlDataAdapter(  
  "SELECT * FROM dbo.Customers", connection);  
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);  
builder.QuotePrefix = "[";  
builder.QuoteSuffix = "]";  

SelectCommand の変更Modifying the SelectCommand

INSERT、UPDATE、または DELETE の各コマンドを自動生成した後に CommandTextSelectCommand を変更すると、例外が発生することがあります。If you modify the CommandText of the SelectCommand after the INSERT, UPDATE, or DELETE commands have been automatically generated, an exception may occur. 変更された SelectCommand.CommandText に、INSERT、UPDATE、または DELETE の各コマンドの自動生成時に使用した SelectCommand.CommandText と矛盾するスキーマ情報が含まれている場合、後続の DataAdapter.Update メソッド呼び出しでアクセスする列は SelectCommand によって参照された現在のテーブルには存在しない可能性があり、例外が発生します。If the modified SelectCommand.CommandText contains schema information that is inconsistent with the SelectCommand.CommandText used when the insert, update, or delete commands were automatically generated, future calls to the DataAdapter.Update method may attempt to access columns that no longer exist in the current table referenced by the SelectCommand, and an exception will be thrown.

CommandBuilderRefreshSchema メソッドを呼び出すことで、自動的にコマンドを生成する CommandBuilder が使用するスキーマ情報を更新できます。You can refresh the schema information used by the CommandBuilder to automatically generate commands by calling the RefreshSchema method of the CommandBuilder.

どのコマンドが自動的に生成されたかを確認するには、GetInsertCommand オブジェクトの GetUpdateCommandGetDeleteCommandCommandBuilder の各メソッドを使用して、自動的に生成されたコマンドへの参照を取得し、関連付けられているコマンドの CommandText プロパティを確認します。If you want to know what command was automatically generated, you can obtain a reference to the automatically generated commands by using the GetInsertCommand, GetUpdateCommand, and GetDeleteCommand methods of the CommandBuilder object and checking the CommandText property of the associated command.

自動的に生成された更新コマンドをコンソールに出力するコード サンプルを次に示します。The following code example writes to the console the update command that was automatically generated.

Console.WriteLine(builder.GetUpdateCommand().CommandText)  
Console.WriteLine(builder.GetUpdateCommand().CommandText);

次の例では、Customers データセットに custDS テーブルを作成し直します。The following example recreates the Customers table in the custDS dataset. Refreshschemaメソッドが呼び出され、この新しい列情報で自動的に生成されたコマンドが更新されます。The RefreshSchema method is called to refresh the automatically generated commands with this new column information.

' Assumes an open SqlConnection and SqlDataAdapter inside of a Using block.  
adapter.SelectCommand.CommandText = _  
  "SELECT CustomerID, ContactName FROM dbo.Customers"  
builder.RefreshSchema()  
  
custDS.Tables.Remove(custDS.Tables("Customers"))  
adapter.Fill(custDS, "Customers")  
// Assumes an open SqlConnection and SqlDataAdapter inside of a using block.  
adapter.SelectCommand.CommandText =   
  "SELECT CustomerID, ContactName FROM dbo.Customers";  
builder.RefreshSchema();  
  
custDS.Tables.Remove(custDS.Tables["Customers"]);  
adapter.Fill(custDS, "Customers");  

関連項目See also