Domanda

Quali sono le migliori pratiche per eseguire transazioni in C # .Net 2.0. Quali sono le classi che dovrebbero essere utilizzate? Quali sono le insidie ??da cercare, ecc. Tutto ciò che commette e ripristina le cose. Sto appena iniziando un progetto in cui potrei dover fare alcune transazioni mentre inserisco i dati nel DB. Eventuali risposte o collegamenti anche su elementi di base relativi alle transazioni sono i benvenuti.

È stato utile?

Soluzione

Esistono 2 tipi principali di transazioni; transazioni di connessione e transazioni ambientali. Una transazione di connessione (come SqlTransaction) è legata direttamente alla connessione db (come SqlConnection), il che significa che devi continuare a passare la connessione in giro - OK in alcuni casi, ma non consente " crea / usa / rilascia " ; utilizzo e non consente il lavoro cross-db. Un esempio (formattato per lo spazio):

using (IDbTransaction tran = conn.BeginTransaction()) {
    try {
        // your code
        tran.Commit();
    }  catch {
        tran.Rollback();
        throw;
    }
}

Non troppo disordinato, ma limitato alla nostra connessione "conn". Se vogliamo richiamare metodi diversi, ora dobbiamo passare " conn " intorno.

L'alternativa è una transazione ambientale; novità di .NET 2.0, l'oggetto TransactionScope (Sistema .Transactions.dll) consente l'utilizzo in una serie di operazioni (i provider adatti verranno automaticamente inclusi nella transazione ambientale). Ciò rende più semplice adattarsi al codice esistente (non transazionale) e parlare con più fornitori (anche se DTC verrà coinvolto se si parla con più di uno).

Ad esempio:

using(TransactionScope tran = new TransactionScope()) {
    CallAMethodThatDoesSomeWork();
    CallAMethodThatDoesSomeMoreWork();
    tran.Complete();
}

Nota qui che i due metodi sono in grado di gestire le proprie connessioni (apri / usa / chiudi / disponi), ma diventeranno silenziosamente parte della transazione ambientale senza che dovremo passare nulla.

Se si verificano errori di codice, Dispose () verrà chiamato senza Complete (), quindi verrà eseguito il rollback. L'annidamento previsto, ecc. È supportato, sebbene non sia possibile ripristinare una transazione interna ma completare la transazione esterna: se qualcuno non è soddisfatto, la transazione viene interrotta.

L'altro vantaggio di TransactionScope è che non è legato solo ai database; qualsiasi fornitore consapevole delle transazioni può utilizzarlo. WCF, per esempio. Oppure ci sono anche alcuni modelli di oggetti compatibili con TransactionScope (ovvero classi .NET con funzionalità di rollback - forse più facile di un ricordo, anche se non ho mai usato questo approccio da solo).

Tutto sommato, un oggetto molto, molto utile.

Alcuni avvertimenti:

  • Su SQL Server 2000, TransactionScope passerà immediatamente a DTC; questo è stato risolto in SQL Server 2005 e versioni successive, può utilizzare LTM (molto meno overhead) fino a quando non si parla con 2 origini ecc., quando viene elevato a DTC.
  • Esiste un glitch che significa che potrebbe essere necessario modificare la tua stringa di connessione

Altri suggerimenti

protected void Button1_Click(object sender, EventArgs e)
   {


       using (SqlConnection connection1 = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database.mdf;Integrated Security=True;User Instance=True"))
       {
           connection1.Open();

           // Start a local transaction.
           SqlTransaction sqlTran = connection1.BeginTransaction();

           // Enlist a command in the current transaction.
           SqlCommand command = connection1.CreateCommand();
           command.Transaction = sqlTran;

           try
           {
               // Execute two separate commands.
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('a','b','c')";
               command.ExecuteNonQuery();
               command.CommandText =
                "insert into [doctor](drname,drspecialization,drday) values ('x','y','z')";
               command.ExecuteNonQuery();

               // Commit the transaction.
               sqlTran.Commit();
               Label3.Text = "Both records were written to database.";
           }
           catch (Exception ex)
           {
               // Handle the exception if the transaction fails to commit.
               Label4.Text = ex.Message;


               try
               {
                   // Attempt to roll back the transaction.
                   sqlTran.Rollback();
               }
               catch (Exception exRollback)
               {
                   // Throws an InvalidOperationException if the connection 
                   // is closed or the transaction has already been rolled 
                   // back on the server.
                   Label5.Text = exRollback.Message;

               }
           }
       }


   }

Puoi anche concludere la transazione nella propria procedura memorizzata e gestirla in questo modo invece di eseguire transazioni in C # stesso.

se ne hai solo bisogno per cose relative a db, alcuni Mapper OR (ad esempio NHibernate) supportano i transactinos fuori dalla scatola per impostazione predefinita.

Dipende anche da ciò di cui hai bisogno. Per le transazioni SQL di base puoi provare a fare transazioni TSQL usando BEGIN TRANS e COMMIT TRANS nel tuo codice. Questo è il modo più semplice ma ha complessità e devi fare attenzione a impegnarti correttamente (e ripristinare).

Vorrei usare qualcosa come

SQLTransaction trans = null;
using(trans = new SqlTransaction)
{
    ...
    Do SQL stuff here passing my trans into my various SQL executers
    ...
    trans.Commit  // May not be quite right
}

Qualsiasi errore ti farà uscire dal utilizzando e la transazione eseguirà sempre il commit o il rollback (a seconda di ciò che gli dici di fare). Il problema più grande che abbiamo dovuto affrontare era assicurarci che fosse sempre commesso. L'utilizzo garantisce che l'ambito della transazione sia limitato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top