Usare System.Transactions
Si applica a:SQL Server
Lo spazio dei nomi System.Transactions
fornisce un framework di transazioni completamente integrato con l'integrazione di ADO.NET e SQL Server Common Language Runtime (CLR). La classe System.Transactions.TransactionScope
crea un blocco di codice transazionale inserendo in modo implicito le connessioni in una transazione distribuita. È necessario chiamare il metodo Complete
alla fine del blocco di codice contrassegnato dal TransactionScope
. Il metodo Dispose
viene richiamato quando l'esecuzione del programma lascia un blocco di codice, causando l'interruzione della transazione se il metodo Complete
non viene chiamato. Se è stata generata un'eccezione che causa l'uscita dell'ambito dal codice, la transazione viene considerata sospesa.
È consigliabile utilizzare un blocco using
per assicurarsi che il metodo Dispose
venga chiamato sull'oggetto TransactionScope
quando il blocco using
viene chiuso. Il mancato commit o il rollback delle transazioni in sospeso può compromettere seriamente le prestazioni perché il timeout predefinito per il TransactionScope
è di un minuto. Se non si usa un'istruzione using
, è necessario eseguire tutte le operazioni in un blocco Try
e chiamare in modo esplicito il metodo Dispose
nel blocco Finally
.
Se si verifica un'eccezione all'interno del TransactionScope
, la transazione viene contrassegnata come incoerente e viene abbandonata. Viene eseguito il rollback quando il TransactionScope
viene eliminato. Se non si verifica alcuna eccezione, viene eseguito il commit delle transazioni partecipanti.
TransactionScope
deve essere usato solo quando si accede a origini dati locali e remote o gestori di risorse esterne, perché TransactionScope
sempre fa sì che le transazioni vengano alzate di livello, anche se vengono usate solo all'interno di una connessione di contesto.
La classe TransactionScope
crea una transazione con un System.Transactions.Transaction.IsolationLevel
di Serializable
per impostazione predefinita. A seconda dell'applicazione, è possibile abbassare il livello di isolamento per evitare che si verifichi un numero elevato di contese.
Nota
È consigliabile eseguire solo aggiornamenti, inserimenti ed eliminazioni all'interno di transazioni distribuite sui server remoti in quanto tali operazioni comportano un notevole consumo di risorse del database. Se l'operazione verrà eseguita nel server locale, non è necessaria una transazione distribuita e una transazione locale sarà sufficiente.
SELECT
istruzioni potrebbero bloccare inutilmente le risorse del database e in alcuni scenari potrebbe essere necessario usare le transazioni per le selezioni. Tutto il lavoro che non riguarda il database deve essere svolto all'esterno dell'ambito della transazione, a meno che non coinvolga altri gestori di risorse inclusi nella transazione.
Sebbene un'eccezione all'interno dell'ambito della transazione impedisca il commit della transazione, la classe TransactionScope
non ha alcun provisioning per il rollback delle modifiche apportate dal codice all'esterno dell'ambito della transazione stessa. Se è necessario eseguire un'azione quando viene eseguito il rollback della transazione, è necessario scrivere la propria implementazione dell'interfaccia System.Transactions.IEnlistmentNotification
ed eseguire in modo esplicito l'integrazione nella transazione.
Esempi
Per usare System.Transactions
, è necessario avere un riferimento al file di System.Transactions.dll.
Il codice seguente illustra come creare una transazione che può essere alzata di livello rispetto a due istanze diverse di SQL Server. Queste istanze sono rappresentate da due oggetti System.Data.SqlClient.SqlConnection
diversi, di cui viene eseguito il wrapping in un blocco TransactionScope
. Il codice crea il blocco TransactionScope
con un'istruzione using
e apre la prima connessione, che lo inserisce automaticamente nell'TransactionScope
. La transazione viene integrata inizialmente come transazione lightweight, non come transazione completamente distribuita. Il codice presuppone l'esistenza della logica condizionale (omessa per brevità). Apre la seconda connessione solo se necessario, integrandola nel TransactionScope
.
Quando la connessione è aperta, la transazione viene promossa automaticamente a una transazione completamente distribuita. Il codice richiama quindi TransactionScope.Complete
, che esegue il commit della transazione. Il codice elimina le due connessioni quando si escono dalle istruzioni using
per le connessioni. Il metodo TransactionScope.Dispose
per il TransactionScope
viene chiamato automaticamente alla chiusura del blocco di using
per il TransactionScope
. Se è stata generata un'eccezione in qualsiasi punto del blocco TransactionScope
, Complete
non viene chiamato e la transazione distribuita esegue il rollback quando viene eliminato il TransactionScope
.
using (TransactionScope transScope = new TransactionScope())
{
using (SqlConnection connection1 = new
SqlConnection(connectString1))
{
// Opening connection1 automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Do work in the first connection.
// Assumes conditional logic in place where the second
// connection will only be opened as needed.
using (SqlConnection connection2 = new
SqlConnection(connectString2))
{
// Open the second connection, which enlists the
// second connection and promotes the transaction to
// a full distributed transaction.
connection2.Open();
// Do work in the second connection.
}
}
// The Complete method commits the transaction.
transScope.Complete();
}