Condividi tramite


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();
}