Génération de commandes avec CommandBuildersGenerating Commands with CommandBuilders

Lorsque la propriété SelectCommand est spécifiée de manière dynamique au moment de l'exécution, par l'intermédiaire d'un outil de requête qui prend une commande textuelle provenant de l'utilisateur par exemple, il est possible que vous ne puissiez pas spécifier les propriétés InsertCommand, UpdateCommand ou DeleteCommand appropriées au moment de la conception.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. Si l'objet DataTable est mappé à une table de base de données unique ou est généré par elle, vous pouvez tirer parti de l'objet DbCommandBuilder pour générer automatiquement les propriétés DeleteCommand, InsertCommand et UpdateCommand de l'objet 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.

Vous devez au minimum définir la propriété SelectCommand afin que la génération de automatique de commandes fonctionne.As a minimum requirement, you must set the SelectCommand property in order for automatic command generation to work. Le schéma de table extrait par la propriété SelectCommand détermine la syntaxe des instructions INSERT, UPDATE et DELETE générées automatiquement.The table schema retrieved by the SelectCommand property determines the syntax of the automatically generated INSERT, UPDATE, and DELETE statements.

L'objet DbCommandBuilder doit exécuter SelectCommand afin de retourner les métadonnées nécessaires à la construction des commandes INSERT, UPDATE et DELETE SQL.The DbCommandBuilder must execute the SelectCommand in order to return the metadata necessary to construct the INSERT, UPDATE, and DELETE SQL commands. En conséquence, un trajet supplémentaire vers la source de données est nécessaire et peut gêner les performances.As a result, an extra trip to the data source is necessary, and this can hinder performance. Pour parvenir à une performance optimale, spécifiez vos commandes explicitement plutôt que d'utiliser l'objet DbCommandBuilder.To achieve optimal performance, specify your commands explicitly rather than using the DbCommandBuilder.

SelectCommand doit aussi retourner au moins une clé primaire ou une colonne unique.The SelectCommand must also return at least one primary key or unique column. Si aucune n'est présente, une exception InvalidOperation est levée et les commandes ne sont pas générées.If none are present, an InvalidOperation exception is generated, and the commands are not generated.

Lorsqu'il est associé à DataAdapter, l'objet DbCommandBuilder génère automatiquement les propriétés InsertCommand, UpdateCommand et DeleteCommand du DataAdapter si ce sont des références null.When associated with a DataAdapter, the DbCommandBuilder automatically generates the InsertCommand, UpdateCommand, and DeleteCommand properties of the DataAdapter if they are null references. Si une Command existe déjà pour une propriété, la Command existante est utilisée.If a Command already exists for a property, the existing Command is used.

Les vues de base de données qui sont créées en reliant deux ou plusieurs tables ne sont pas considérées comme une table de base de données unique.Database views that are created by joining two or more tables together are not considered a single database table. Dans ce cas, vous ne pouvez pas utiliser l'objet DbCommandBuilder pour générer automatiquement des commandes et devez spécifier vos commandes explicitement.In this instance you cannot use the DbCommandBuilder to automatically generate commands; you must specify your commands explicitly. Pour plus d’informations sur la définition explicite de commandes pour résoudre des DataSet mises à jour vers la source de données, consultez mise à jour des sources de données avec des DataAdapters.For information about explicitly setting commands to resolve updates to a DataSet back to the data source, see Updating Data Sources with DataAdapters.

Il est possible de mapper les paramètres de sortie à la ligne mise à jour d'un DataSet.You might want to map output parameters back to the updated row of a DataSet. Une tâche courante consisterait à extraire la valeur d'un champ Identité généré automatiquement ou d'un horodatage provenant de la source de données.One common task would be retrieving the value of an automatically generated identity field or time stamp from the data source. L'objet DbCommandBuilder ne mappera pas les paramètres de sortie aux colonnes dans une ligne mise à jour par défaut.The DbCommandBuilder will not map output parameters to columns in an updated row by default. Dans ce cas, vous devez explicitement spécifier votre commande.In this instance you must specify your command explicitly. Pour obtenir un exemple de mappage d’un champ d’identité généré automatiquement à une colonne d’une ligne insérée, consultez extraction des valeurs d’identité ou de numérotationautomatique.For an example of mapping an automatically generated identity field back to a column of an inserted row, see Retrieving Identity or Autonumber Values.

Règles pour les commandes générées automatiquementRules for Automatically Generated Commands

Le tableau suivant présente les règles de génération des commandes générées automatiquement.The following table shows the rules for how automatically generated commands are generated.

CommandeCommand RègleRule
InsertCommand Insère une ligne dans la source de données pour toutes les lignes de la table dont la propriété RowState a la valeur Added.Inserts a row at the data source for all rows in the table with a RowState of Added. Insère des valeurs pour toutes les colonnes qui peuvent être mises à jour (mais pas les colonnes comme les identités, les expressions ou les horodatages).Inserts values for all columns that are updateable (but not columns such as identities, expressions, or timestamps).
UpdateCommand Met à jour les lignes dans la source de données pour toutes les lignes de la table dont la propriété RowState a la valeur Modified.Updates rows at the data source for all rows in the table with a RowState of Modified. Met à jour les valeurs de toutes les colonnes à l'exception de celles qui ne peuvent pas être mises à jour, telles que les identités ou les expressions.Updates the values of all columns except for columns that are not updateable, such as identities or expressions. Met à jour toutes les lignes où les valeurs de colonne au niveau de la source de données correspondent aux valeurs de colonne de clé primaire de la ligne et où les colonnes restantes correspondent aux valeurs d'origine de la ligne.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. Pour plus d'informations, voir « Modèle d'accès simultané optimiste pour les mises à jour et les suppressions », plus loin dans cette rubrique.For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.
DeleteCommand Supprime les lignes dans la source de données pour toutes les lignes de la table dont la propriété RowState a la valeur Deleted.Deletes rows at the data source for all rows in the table with a RowState of Deleted. Supprime toutes les lignes où les valeurs de colonne correspondent aux valeurs de colonne de clé primaire de la ligne et où les colonnes restantes de la source de données correspondent aux valeurs d'origine de la ligne.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. Pour plus d'informations, voir « Modèle d'accès simultané optimiste pour les mises à jour et les suppressions », plus loin dans cette rubrique.For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.

Modèle d'accès simultané optimiste pour les mises à jour et les suppressionsOptimistic Concurrency Model for Updates and Deletes

La logique de génération automatique de commandes pour les instructions UPDATE et DELETE est basée sur l' accès concurrentiel optimiste, autrement dit, les enregistrements ne sont pas verrouillés pour modification et peuvent être modifiés par d’autres utilisateurs ou processus à tout moment.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. Puisqu'un enregistrement aurait pu être modifié après avoir été retourné de l'instruction SELECT mais avant que l'instruction UPDATE ou DELETE ne soit émise, l'instruction UPDATE ou DELETE générée automatiquement contient une clause WHERE spécifiant qu'une ligne n'est mise à jour que si elle contient toutes les valeurs d'origine et n'a pas été supprimée de la source de données.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. Cela permet d'éviter le remplacement de nouvelles données.This is done to avoid overwriting new data. Quand une mise à jour générée automatiquement tente de mettre à jour une ligne qui a été supprimée ou qui ne contient pas les valeurs d'origine qui se trouvent dans l'objet DataSet, la commande n'affecte pas d'enregistrement et un objet DBConcurrencyException est généré.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.

Si vous souhaitez que les instructions UPDATE ou DELETE soient exécutées indépendamment des valeurs d'origine, vous devez explicitement définir la propriété UpdateCommand pour le DataAdapter et ne pas compter sur la génération automatique de commandes.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.

Limites de la logique de génération automatique de commandesLimitations of Automatic Command Generation Logic

Les limites suivantes s'appliquent à la génération automatique de commandes.The following limitations apply to automatic command generation.

Tables dissociées uniquementUnrelated Tables Only

La logique de génération automatique de commandes génère des instructions INSERT, UPDATE ou DELETE pour les tables autonomes sans prendre en compte les relations avec les autres tables au niveau de la source de données.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. En conséquence, il est possible que l'appel à Update, pour soumettre les modifications pour une colonne qui participe à une contrainte de clé étrangère dans la base de données, échoue.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. Pour éviter cette exception, n'utilisez pas l'objet DbCommandBuilder pour mettre à jour les colonnes impliquées dans une contrainte de clé étrangère et spécifiez plutôt explicitement les instructions utilisées pour effectuer l'opération.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.

Noms de table et de colonneTable and Column Names

La logique de génération automatique de commandes peut échouer si les noms de colonne ou de table contiennent des caractères spéciaux (notamment espaces, points, points d'interrogation ou autres caractères non alphanumériques), même s'ils sont délimités par des crochets.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. Selon le fournisseur, le fait de définir les paramètres QuotePrefix et QuoteSuffix peut permettre à la logique de génération de traiter les espaces, mais pas les caractères spéciaux d'échappement.Depending on the provider, setting the QuotePrefix and QuoteSuffix parameters may allow the generation logic to process spaces, but it cannot escape special characters. Les noms de table qualifiés complets sous la forme Catalog. Schema. table sont pris en charge.Fully qualified table names in the form of catalog.schema.table are supported.

Utilisation de CommandBuilder pour générer automatiquement une instruction SQLUsing the CommandBuilder to Automatically Generate an SQL Statement

Pour générer automatiquement des instructions SQL pour un DataAdapter, commencez par définir la propriété SelectCommand du DataAdapter, puis créez un objet CommandBuilder et spécifiez comme argument le DataAdapter pour lequel l’objet CommandBuilder génère automatiquement des instructions SQL.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 = "]";  

Modification de SelectCommandModifying the SelectCommand

Si vous modifiez le CommandText du SelectCommand après la génération automatique des commandes INSERT, UPDATE ou DELETE, une exception peut se produire.If you modify the CommandText of the SelectCommand after the INSERT, UPDATE, or DELETE commands have been automatically generated, an exception may occur. Si le SelectCommand.CommandText modifié contient des informations de schéma qui ne sont pas cohérentes par rapport au SelectCommand.CommandText utilisé lors de la génération automatique des commandes d'insertion, de mise à jour ou de suppression, les appels ultérieurs à la méthode DataAdapter.Update peuvent chercher à accéder à des colonnes qui n'existent plus dans la table actuelle référencée par SelectCommand et une exception sera levée.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.

Vous pouvez actualiser les informations de schéma utilisées par CommandBuilder pour générer automatiquement les commandes en appelant la méthode RefreshSchema du CommandBuilder.You can refresh the schema information used by the CommandBuilder to automatically generate commands by calling the RefreshSchema method of the CommandBuilder.

Si vous souhaitez connaître les commandes générées automatiquement, vous pouvez en obtenir une référence en appliquant les méthodes GetInsertCommand, GetUpdateCommand et GetDeleteCommand de l'objet CommandBuilder et en vérifiant la propriété CommandText de la commande associée.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.

L'exemple de code suivant écrit sur la console la commande de mise à jour générée automatiquement.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);

L'exemple suivant recrée la table Customers dans le dataset custDS.The following example recreates the Customers table in the custDS dataset. La méthode RefreshSchema est appelée pour actualiser les commandes générées automatiquement avec ces nouvelles informations de colonne.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");  

Voir aussiSee also