Gestione delle transazioni con il .NET Framework 2.0

di Ugo Lattanzi, in ASP.NET 2.0,

Molte delle applicazioni odierne richiedono uno storage per persistere i dati e in molti casi esso è rappresentato da un database. Ormai tutti i DBMS (Database Management System) moderni ed, in particolare, SQL Server e Oracle supportano le transazioni. Di che si tratta?

Una transazione è una sequenza di operazioni implementate per lo più dai DBMS che riguardano un insieme di dati da modificare. La sequenza di azioni può concludersi con un successo o con un fallimento: in caso di successo, il risultato delle operazioni diventa permanente e lo stato del sistema cambia di conseguenza, mentre, in caso di insuccesso, lo stato viene ripristinato nella situazione iniziale.

Perchè le transazioni possano essere tali, esse devono rispettare quattro caratteristiche solitamente conosciute con l'acronimo ACID, che sta ad indicare:

  • Atomic: tutte le operazioni devono andare a buon fine, quindi, una volta terminata, l'esecuzione di una transazione si può definire totalmente conclusa o del tutto nulla;
  • Consistent: tra lo stato antecedente e lo stato successivo alla transazione non devono essere violati i vincoli di integrità, ovvero non si devono verificare situazioni di inconsistenza sui dati;
  • Isolated: gli effetti della transazione non sono visibili esternamente ad essa finchè non si è conclusa con un successo;
  • Durable: al termine della transazione i dati devono essere memorizzati in modo persistente.

Un primo semplice esempio

Consideriamo un esempio per capire il campo di azione. Supponiamo di avere un database dove siano contenute due ipotetiche tabelle Users e Roles, contenenti rispettivamente le informazioni relative agli utenti ed ai ruoli da essi ricoperti. Nel caso in cui sia necessario memorizzare i dati di un nuovo utente in Users, occorre contestualmente inserirne i ruoli nella tabella Roles.

L'ordine di esecuzione impone quindi di memorizzare prima i dati dell'utente e successivamente i suoi ruoli, relazionandoli in base al loro identificativo (PK). Supponiamo che, per qualche motivo, durante la memorizzazione dei ruoli qualcosa vada storto: in questo caso risulta necessario ripristinare la situazione di partenza ed informare il client che qualcosa non è andato a buon fine durante la procedura di memorizzazione.

Effettuare un inserimento e, in caso di errore, una cancellazione di compensazione è una pessima soluzione: innanzitutto perchè si effettuano più query (con una sequenza del tipo: primo inserimento, secondo inserimento, errore, cancellazione del primo record), in secondo luogo perchè durante l'inserimento del ruolo non abbiamo la certezza che qualche altra operazione non vada ad interessare il record relativo all'utente appena inserito. In situazioni come quella appena descritta ci vengono in aiuto le transazioni.

Le transazioni di ADO.NET

Nel .NET Framework gli oggetti che rappresentano le transazioni nell'ambito dei managed data provider (per esempio SqlTransaction, OleDbTransaction, OdbcTransaction) derivano dalla classe astratta System.Data.Common.DbTransaction che implementa a sua volta l'interfaccia IDbTransaction, esponendo così i metodi e le proprietà necessarie per la loro gestione:

  • proprietà Connection: contiene la connessione al database su cui la transazione è attiva;


  • metodo Commit(): funzione che si invoca per rendere permanenti le modifiche quando tutte le operazioni sui dati sono state effettuate;


  • metodo RollBack(): esattamente l'opposto del metodo Commit(), ossia annulla tutte le operazioni incluse nella transazione. Normalmente questa funzione viene invocata quando nell'operazione di modifica si scatena un'eccezione che ne impedisce la conclusione;


  • proprietà IsolationLevel: rappresenta il livello di isolamento della transazione. I valori possibili, contenuti nell'enumerazione System.Data.IsolationLevel, sono nell'ordine:

    1. Chaos: le modifiche in sospeso dalle transazioni più isolate non possono essere sovrascritte;
    2. ReadCommited: è quello impostato di default nei managed data provider del .NET Framework e permette che i dati interessati da una transazione siano accessibili da una seconda transazione soltanto dopo che la prima è andata a termine;
    3. ReadUncommited: è il contrario della precedente, dal momento che consente la lettura dei dati da altre transazioni prima che questa sia portata a termine;
    4. RepeatableRead: si comporta allo stesso modo di ReadCommited, ma con la variante che, se durante la transazione vengono interrogati più dati, questi vengono restituiti esattamente come sono stati prelevati la prima volta, anche se qualche altra transazione li ha modificati. Ovviamente, tenendo in memoria una copia dei dati, un approccio con questo tipo di isolamento è meno performante dei precedenti;
    5. Serializable: è il criterio più restrittivo che imposta un lock sui dati interessati dalla transazione impedendo eventuali modifiche esterne;
    6. Snapshot: indica che in una transazione non è possibile vedere le modifiche apportate in altre transazioni, anche se viene ripetuto il comando di lettura. In questo caso una versione dei dati viene mantenuta in memoria in modo tale che possano essere comunque eseguite letture su di essi indipendentemente dal fatto che i dati siano stati modificati;
    7. Unspecified: non specifica nessun tipo particolare di Isolation Level e fa si che sia il provider ADO.NET ad impostare il livello predefinito (in generale è ReadCommitted).

Le transazioni ADO.NET si applicano nell'ambito di un'unica connessione ad una sorgente dati. L'inizio della transazione avviene invocando il metodo BeginTransaction() dell'oggetto connessione, come mostra il codice seguente:

SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
SqlTransaction transaction = conn.BeginTransaction();
try
{
  // Eseguo tutti i comandi necessari sul database.
  // ...
  // ...
  // ...
  Transaction.Commit();
}
catch
{
  // Si è verificato un errore.
  Transaction.RollBack();
}
finally
{
  conn.Close();
}
3 pagine in totale: 1 2 3

Attenzione: Questo articolo contiene un allegato.

Contenuti dell'articolo

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti