Condividi tramite


Generazione di comandi con CommandBuilders

Quando la proprietà SelectCommand viene specificata dinamicamente al momento dell'esecuzione, ad esempio tramite uno strumento di query che accetta un comando testuale dall'utente, potrebbe non essere possibile specificare InsertCommand, UpdateCommand, o DeleteCommand al momento della progettazione. Se il DataTable è mappato su o viene generato da una singola tabella di database, è possibile sfruttare l'oggetto DbCommandBuilder per generare automaticamente il DeleteCommand, il InsertCommand e il UpdateCommand del DbDataAdapter.

Come requisito minimo, è necessario impostare la proprietà affinché la SelectCommand generazione automatica dei comandi funzioni. Lo schema della SelectCommand tabella recuperato dalla proprietà determina la sintassi delle istruzioni INSERT, UPDATE e DELETE generate automaticamente.

Il DbCommandBuilder deve eseguire il SelectCommand per poter restituire i metadati necessari per costruire i comandi SQL INSERT, UPDATE e DELETE. Di conseguenza, è necessario un ulteriore viaggio all'origine dati e ciò può ostacolare le prestazioni. Per ottenere prestazioni ottimali, specificare i comandi in modo esplicito anziché usare .DbCommandBuilder

È inoltre necessario che SelectCommand restituisca almeno una chiave primaria o una colonna univoca. Se non sono presenti, viene generata un'eccezione InvalidOperation e i comandi non vengono generati.

Quando associato a DataAdapter, l'oggetto DbCommandBuilder genera automaticamente le proprietà InsertCommand, UpdateCommand e DeleteCommand di DataAdapter se sono riferimenti null. Se esiste già un Command oggetto per una proprietà, viene utilizzato l'oggetto esistente Command .

Le viste di database create unendo due o più tabelle insieme non vengono considerate una singola tabella di database. In questa istanza non è possibile utilizzare il DbCommandBuilder per generare automaticamente comandi; è necessario specificare i comandi in modo esplicito. Per informazioni sull'impostazione esplicita dei comandi per applicare gli aggiornamenti a un'origine dati DataSet, vedere Aggiornamento di origini dati con DataAdapters.

Potresti voler mappare i parametri di output alla riga aggiornata di un oggetto DataSet. Un'attività comune consiste nel recuperare il valore di un campo identità generato automaticamente o di una marca temporale dall'origine dei dati. Il DbCommandBuilder di default non eseguirà il mapping dei parametri di output alle colonne in una riga aggiornata. In questa istanza è necessario specificare il comando in modo esplicito. Per un esempio di associazione di un campo Identity generato automaticamente a una colonna di una riga aggiunta, vedere Recupero di valori identity o numerazione automatica.

Regole per i comandi generati automaticamente

Nella tabella seguente vengono mostrate le regole per la generazione automatica dei comandi.

Comando Regola
InsertCommand Inserisce una riga nell'origine dati per ogni riga della tabella con un valore di RowState pari a Added. Inserisce valori per tutte le colonne aggiornabili, ma non per colonne quali identità, espressioni o timestamp.
UpdateCommand Aggiorna le righe nell'origine dati per tutte le righe della tabella con un RowState di Modified. Aggiorna i valori di tutte le colonne ad eccezione delle colonne che non sono aggiornabili, ad esempio identità o espressioni. Aggiorna tutte le righe in cui i valori di colonna nell'origine dati corrispondono ai valori della colonna chiave primaria della riga e dove le colonne rimanenti nell'origine dati corrispondono ai valori originali della riga. Per altre informazioni, vedere "Modello di concorrenza ottimistica per aggiornamenti ed eliminazioni" più avanti in questo argomento.
DeleteCommand Elimina le righe nell'origine dati per tutte le righe della tabella con un valore di RowState pari a Deleted. Elimina tutte le righe in cui i valori della colonna corrispondono ai valori della colonna chiave primaria della riga e in cui le colonne rimanenti nell'origine dati corrispondono ai valori originali della riga. Per altre informazioni, vedere "Modello di concorrenza ottimistica per aggiornamenti ed eliminazioni" più avanti in questo argomento.

Modello di concorrenza ottimistica per aggiornamenti ed eliminazioni

La logica per la generazione automatica dei comandi per le istruzioni UPDATE e DELETE si basa sulla concorrenza ottimistica, ovvero i record non sono bloccati per la modifica e possono essere modificati da altri utenti o processi in qualsiasi momento. Poiché un record potrebbe essere stato modificato dopo che è stato restituito dall'istruzione SELECT, ma prima dell'emissione dell'istruzione UPDATE o DELETE, l'istruzione UPDATE o DELETE generata automaticamente contiene una clausola WHERE, specificando che una riga viene aggiornata solo se contiene tutti i valori originali e non è stata eliminata dall'origine dati. Questa operazione viene eseguita per evitare di sovrascrivere nuovi dati. Quando un aggiornamento generato automaticamente tenta di aggiornare una riga eliminata o che non contiene i valori originali trovati in DataSet, il comando non influisce sui record e viene generata un'eccezione DBConcurrencyException .

Se si desidera completare l'istruzione UPDATE o DELETE indipendentemente dai valori originali, è necessario impostare in modo esplicito il UpdateCommand per il DataAdapter e non basarsi sulla generazione automatica dei comandi.

Limitazioni della logica di generazione automatica dei comandi

Le limitazioni seguenti si applicano alla generazione automatica dei comandi.

Solo tabelle non correlate

La logica di generazione automatica dei comandi genera istruzioni INSERT, UPDATE o DELETE per tabelle autonome senza tenere conto delle relazioni con altre tabelle nell'origine dati. Di conseguenza, è possibile che si verifichi un errore quando si chiama Update per inviare modifiche per una colonna che partecipa a un vincolo di chiave esterna nel database. Per evitare questa eccezione, non utilizzare DbCommandBuilder per l'aggiornamento delle colonne coinvolte in un vincolo di chiave esterna; specificare invece esplicitamente le istruzioni utilizzate per eseguire l'operazione.

Nomi di tabella e colonna

La logica di generazione automatica dei comandi può non riuscire se i nomi di colonna o di tabella contengono caratteri speciali, ad esempio spazi, punti, virgolette o altri caratteri non alfanumerici, anche se delimitati da parentesi quadre. A seconda del provider, l'impostazione dei parametri QuotePrefix e QuoteSuffix può consentire alla logica di generazione di elaborare gli spazi, ma non può gestire correttamente i caratteri speciali. Sono supportati nomi di tabella completi sotto forma di catalog.schema.table .

Uso di CommandBuilder per generare automaticamente un'istruzione SQL

Per generare automaticamente istruzioni SQL per un DataAdapteroggetto , impostare prima la SelectCommand proprietà di DataAdapter, quindi creare un CommandBuilder oggetto e specificare come argomento per DataAdapter il quale CommandBuilder genererà automaticamente istruzioni SQL.

' 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 del comando Select

Se si modifica il CommandText del SelectCommand dopo che i comandi INSERT, UPDATE o DELETE sono stati generati automaticamente, potrebbe verificarsi un'eccezione. Se l'oggetto modificato SelectCommand.CommandText contiene informazioni sullo schema non coerenti con l'oggetto SelectCommand.CommandText utilizzato quando i comandi di inserimento, aggiornamento o eliminazione sono stati generati automaticamente, le chiamate future al DataAdapter.Update metodo potrebbero tentare di accedere alle colonne che non esistono più nella tabella corrente a cui fa riferimento il SelectCommande verrà generata un'eccezione.

È possibile aggiornare le informazioni sullo schema usate da CommandBuilder per generare automaticamente i comandi chiamando il RefreshSchema metodo di CommandBuilder.

Per sapere quale comando è stato generato automaticamente, è possibile ottenere un riferimento ai comandi generati automaticamente usando i metodi GetInsertCommand, GetUpdateCommand e GetDeleteCommand dell'oggetto CommandBuilder e controllando la proprietà CommandText del comando associato.

Nell'esempio di codice seguente viene scritto nella console il comando di aggiornamento generato automaticamente.

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

Nell'esempio seguente viene ricreata la Customers tabella nel custDS set di dati. Il metodo RefreshSchema viene chiamato per aggiornare i comandi generati automaticamente con queste nuove informazioni sulla colonna.

' 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 anche