Generazione di comandi tramite CommandBuildersGenerating Commands with CommandBuilders

Se la proprietà SelectCommand viene specificata in modo dinamico in fase di esecuzione, ad esempio mediante uno strumento per query che accetta un comando testuale dell'utente, potrebbe non essere possibile specificare l'appropriato InsertCommand, UpdateCommand o DeleteCommand in fase di progettazione.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. Se DataTable esegue il mapping o viene generato da una singola tabella di database, è possibile usare l'oggetto DbCommandBuilder per generare automaticamente gli oggetti DeleteCommand, InsertCommand e UpdateCommand di 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.

Come requisito minimo, è necessario impostare la proprietà SelectCommand affinché la generazione automatica del comando venga eseguita correttamente.As a minimum requirement, you must set the SelectCommand property in order for automatic command generation to work. Lo schema della tabella recuperato dalla proprietà SelectCommand determina la sintassi delle istruzioni INSERT, UPDATE e DELETE generate automaticamente.The table schema retrieved by the SelectCommand property determines the syntax of the automatically generated INSERT, UPDATE, and DELETE statements.

DbCommandBuilder deve eseguire SelectCommand in modo da restituire i metadati necessari per creare i comandi SQL INSERT, UPDATE e DELETE.The DbCommandBuilder must execute the SelectCommand in order to return the metadata necessary to construct the INSERT, UPDATE, and DELETE SQL commands. Di conseguenza, è necessario un ulteriore percorso all'origine dati che può ridurre le prestazioni.As a result, an extra trip to the data source is necessary, and this can hinder performance. Per ottenere prestazioni ottimali, specificare i comandi in modo esplicito anziché usare DbCommandBuilder.To achieve optimal performance, specify your commands explicitly rather than using the DbCommandBuilder.

È inoltre necessario che SelectCommand restituisca almeno una chiave primaria o una colonna univoca.The SelectCommand must also return at least one primary key or unique column. In caso contrario, viene generata un'eccezione InvalidOperation e i comandi non vengono generati.If none are present, an InvalidOperation exception is generated, and the commands are not generated.

Quando è associato a un DataAdapter, DbCommandBuilder genera automaticamente le proprietà InsertCommand, UpdateCommand e DeleteCommand del DataAdapter, se queste sono riferimenti Null.When associated with a DataAdapter, the DbCommandBuilder automatically generates the InsertCommand, UpdateCommand, and DeleteCommand properties of the DataAdapter if they are null references. Se esiste già un oggetto Command per una proprietà, viene usato l'oggetto Command esistente.If a Command already exists for a property, the existing Command is used.

Le visualizzazioni di database create dall'unione di due o più tabelle non vengono considerate un'unica tabella di database.Database views that are created by joining two or more tables together are not considered a single database table. In questo caso non è possibile usare DbCommandBuilder per generare automaticamente i comandi ed è necessario specificarli in modo esplicito.In this instance you cannot use the DbCommandBuilder to automatically generate commands; you must specify your commands explicitly. Per informazioni su come impostare in modo esplicito i comandi per DataSet risolvere gli aggiornamenti di un nuovo oggetto nell'origine dati, vedere aggiornamento delle origini dati con DataAdapters.For information about explicitly setting commands to resolve updates to a DataSet back to the data source, see Updating Data Sources with DataAdapters.

È possibile eseguire il mapping dei parametri di output alla riga aggiornata di un DataSet.You might want to map output parameters back to the updated row of a DataSet. Un'attività comune sarebbe il recupero del valore di un campo identità generato automaticamente o del timestamp da un'origine dati.One common task would be retrieving the value of an automatically generated identity field or time stamp from the data source. Per impostazione predefinita, DbCommandBuilder non esegue il mapping dei parametri di output sulle colonne in una riga aggiornata.The DbCommandBuilder will not map output parameters to columns in an updated row by default. In questo caso è necessario specificare il comando in modo esplicito.In this instance you must specify your command explicitly. Per un esempio di mapping di un campo Identity generato automaticamente a una colonna di una riga inserita, vedere recupero di valori Identity o Autonumber.For an example of mapping an automatically generated identity field back to a column of an inserted row, see Retrieving Identity or Autonumber Values.

Regole per i comandi generati automaticamenteRules for Automatically Generated Commands

Nella tabella seguente vengono illustrate le regole per generare automaticamente i comandi.The following table shows the rules for how automatically generated commands are generated.

ComandoCommand RegolaRule
InsertCommand Consente di inserire una riga nell'origine dati per ogni riga della tabella con una proprietà RowState uguale a Added.Inserts a row at the data source for all rows in the table with a RowState of Added. I valori vengono inseriti in tutte le colonne aggiornabili, quindi non nelle colonne di identità, espressioni o timestamp.Inserts values for all columns that are updateable (but not columns such as identities, expressions, or timestamps).
UpdateCommand Aggiorna le righe nell'origine dati per tutte le righe della tabella con RowState uguale a Modified.Updates rows at the data source for all rows in the table with a RowState of Modified. I valori vengono aggiornati in tutte le colonne aggiornabili, quindi non nelle colonne di identità o di espressioni.Updates the values of all columns except for columns that are not updateable, such as identities or expressions. Vengono aggiornate tutte le righe in cui i valori delle colonne nell'origine dati corrispondono ai valori delle colonne della chiave primaria della riga e in cui le restanti colonne dell'origine dati corrispondono ai valori originali della riga.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. Per altre informazioni, vedere la sezione "Modello di concorrenza ottimistica per aggiornamenti ed eliminazioni" contenuta in questo argomento.For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.
DeleteCommand Elimina le righe nell'origine dati per tutte le righe della tabella con RowState uguale a Deleted.Deletes rows at the data source for all rows in the table with a RowState of Deleted. Vengono eliminate tutte le righe in cui i valori delle colonne corrispondono ai valori delle colonne della chiave primaria della riga e in cui le restanti colonne dell'origine dati corrispondono ai valori originali della riga.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. Per altre informazioni, vedere la sezione "Modello di concorrenza ottimistica per aggiornamenti ed eliminazioni" contenuta in questo argomento.For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.

Modello di concorrenza ottimistica per aggiornamenti ed eliminazioniOptimistic Concurrency Model for Updates and Deletes

La logica per la generazione automatica di comandi per le istruzioni UPDATE e DELETE è basata sulla concorrenza ottimistica, ovvero i record non sono bloccati per la modifica e possono essere modificati da altri utenti o processi in qualsiasi momento.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. Poiché un record può essere modificato dopo che è stato restituito dall'istruzione SELECT, ma prima che sia eseguita l'istruzione UPDATE o DELETE, nell'istruzione UPDATE o DELETE generata automaticamente è contenuta una clausola WHERE, tale che una riga viene aggiornata solo se contiene tutti i valori originali e non è stata eliminata dall'origine dati.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. In questo modo si evita di sovrascrivere i nuovi dati.This is done to avoid overwriting new data. Nei casi in cui un comando Update generato automaticamente tenta di aggiornare una riga che è stata eliminata o che non contiene i valori originali rilevati in DataSet, il comando non ha alcun effetto sui record e viene generata un'eccezione 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.

Se si desidera che le istruzioni UPDATE o DELETE vengano completate a prescindere dai valori originali, è necessario impostare in modo esplicito UpdateCommand per il DataAdapter e non usare la generazione automatica dei comandi.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.

Limiti della logica per la generazione automatica dei comandiLimitations of Automatic Command Generation Logic

I limiti che seguono si riferiscono alla generazione automatica dei comandi.The following limitations apply to automatic command generation.

Solo tabelle non correlateUnrelated Tables Only

La logica per la generazione automatica dei comandi genera un'istruzione INSERT, UPDATE o DELETE per le tabelle autonome senza tenere conto delle relazioni con altre tabelle nell'origine dati.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. Di conseguenza, è possibile che venga rilevato un errore quando si chiama Update per inviare le modifiche a una colonna che fa parte di un vincolo di chiave esterna nel database.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. Per evitare questa eccezione, non usare DbCommandBuilder per aggiornare le colonne incluse in un vincolo di chiave esterna e specificare in modo esplicito le istruzioni usate per eseguire l'operazione.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.

Nomi di tabelle e colonneTable and Column Names

La logica per la generazione automatica dei comandi potrebbe non essere eseguita correttamente se i nomi delle colonne o delle tabelle contengono caratteri speciali quali spazi, punti, virgolette o altri caratteri non alfanumerici, anche se racchiusi tra parentesi.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. A seconda del provider, l'impostazione dei parametri QuoteSuffix e QuotePrefix può consentire alla logica di generazione di elaborare gli spazi, ma non i caratteri speciali di escape.Depending on the provider, setting the QuotePrefix and QuoteSuffix parameters may allow the generation logic to process spaces, but it cannot escape special characters. Sono supportati i nomi di tabella completi nel formato Catalog. Schema. Table .Fully qualified table names in the form of catalog.schema.table are supported.

Uso di CommandBuilder per generare automaticamente un'istruzione SQLUsing the CommandBuilder to Automatically Generate an SQL Statement

Per generare automaticamente le istruzioni SQL per un oggetto DataAdapter, impostare innanzitutto la proprietà SelectCommand di DataAdapter. Creare quindi un oggetto CommandBuilder e specificare come argomento l'oggetto DataAdapter per il quale l'oggetto CommandBuilder genererà automaticamente le istruzioni 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 = "]";  

Modifica di SelectCommandModifying the SelectCommand

Se si modifica CommandText di SelectCommand dopo la generazione automatica di un comando INSERT, UPDATE o DELETE, è possibile che venga generata un'eccezione.If you modify the CommandText of the SelectCommand after the INSERT, UPDATE, or DELETE commands have been automatically generated, an exception may occur. Se l'oggetto SelectCommand.CommandText modificato contiene informazioni sullo schema che non sono coerenti con l'oggetto SelectCommand.CommandText usato durante la generazione automatica del comando di inserimento, aggiornamento o eliminazione, nelle future chiamate al metodo DataAdapter.Update potrebbe essere eseguito un tentativo di accesso a colonne che non esistono più nella tabella corrente a cui SelectCommand fa riferimento e verrà generata un'eccezione.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.

È possibile aggiornare le informazioni sullo schema usate da CommandBuilder per generare automaticamente i comandi chiamando il metodo RefreshSchema di CommandBuilder.You can refresh the schema information used by the CommandBuilder to automatically generate commands by calling the RefreshSchema method of the CommandBuilder.

Se si desidera conoscere il comando che è stato generato automaticamente, è possibile ottenere un riferimento ai comandi generati automaticamente tramite i metodi GetInsertCommand, GetUpdateCommand e GetDeleteCommand dell'oggetto CommandBuilder e selezionare la proprietà CommandTextdel comando associato.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.

Nell'esempio di codice seguente viene scritto sulla console il comando di aggiornamento che è stato generato automaticamente.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);

Nell'esempio seguente viene ricreata la tabella Customers nel set di dati custDS.The following example recreates the Customers table in the custDS dataset. Il metodo RefreshSchema viene chiamato per aggiornare i comandi generati automaticamente con le nuove informazioni sulla colonna.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");  

Vedere ancheSee also