it-swarm.com.de

Transaktionen in .net

Was sind die Best Practices für Transaktionen in C # .Net 2.0? Welche Klassen sollten verwendet werden? Was sind die Tücken, auf die man achten muss usw. All diese Commit- und Rollback-Dinge. Ich beginne gerade ein Projekt, in dem ich möglicherweise einige Transaktionen ausführen muss, während Daten in die Datenbank eingefügt werden. Alle Antworten oder Links für grundlegende Informationen zu Transaktionen sind willkommen.

Es gibt 2 Hauptarten von Transaktionen; Verbindungstransaktionen und Ambient-Transaktionen. Eine Verbindungstransaktion (wie SqlTransaction) ist direkt an die Datenbankverbindung (wie SqlConnection) gebunden. Dies bedeutet, dass Sie die Verbindung weitergeben müssen - in einigen Fällen OK, aber "create/use/release" nicht zulassen. Nutzung und erlaubt keine db-übergreifende Arbeit. Ein Beispiel (für Leerzeichen formatiert):

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

Nicht zu chaotisch, sondern auf unsere Verbindung "conn" beschränkt. Wenn wir verschiedene Methoden ansprechen wollen, müssen wir jetzt "conn" weitergeben.

Die Alternative ist eine Ambient-Transaktion. Neu in .NET 2.0 ist, dass das TransactionScope -Objekt (System.Transactions.dll) die Verwendung über eine Reihe von Vorgängen ermöglicht (geeignete Anbieter werden automatisch in die Ambient-Transaktion aufgenommen). Dies erleichtert das Nachrüsten in vorhandenen (nicht transaktionsbezogenen) Code und das Sprechen mit mehreren Anbietern (obwohl DTC einbezogen wird, wenn Sie mit mehr als einem Anbieter sprechen).

Beispielsweise:

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

Hierbei ist zu beachten, dass die beiden Methoden ihre eigenen Verbindungen (Öffnen/Verwenden/Schließen/Entsorgen) verarbeiten können, sie jedoch stillschweigend Teil der Ambient-Transaktion werden, ohne dass wir etwas übergeben müssen.

Wenn Ihr Code fehlerhaft ist, wird Dispose () ohne Complete () aufgerufen, sodass ein Rollback durchgeführt wird. Die erwartete Verschachtelung usw. wird unterstützt, obwohl Sie eine innere Transaktion noch nicht rückgängig machen können. Schließen Sie die äußere Transaktion ab. Wenn jemand unzufrieden ist, wird die Transaktion abgebrochen.

Der andere Vorteil von TransactionScope ist, dass es nicht nur an Datenbanken gebunden ist. Jeder transaktionsbewusste Anbieter kann es verwenden. WCF zum Beispiel. Oder es gibt sogar einige TransactionScope-kompatible Objektmodelle (d. H. .NET-Klassen mit Rollback-Funktion - möglicherweise einfacher als ein Erinnerungsstück, obwohl ich diesen Ansatz selbst nie verwendet habe).

Alles in allem ein sehr, sehr nützliches Objekt.

Einige Einschränkungen:

  • Unter SQL Server 2000 wechselt ein TransactionScope sofort zum DTC. Dies ist in SQL Server 2005 und höher behoben. Es kann das LTM (viel weniger Overhead) verwenden, bis Sie mit 2 Quellen usw. sprechen, wenn es auf DTC erhöht ist.
  • Es gibt ein Glitch , das bedeutet, dass Sie möglicherweise Ihre Verbindungszeichenfolge optimieren müssen
261
Marc Gravell
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;

               }
           }
       }


   }
11
Ali Gholizadeh

Sie können die Transaktion auch in eine eigene gespeicherte Prozedur packen und auf diese Weise behandeln, anstatt Transaktionen in C # selbst durchzuführen.

3
Charles Graham

wenn Sie es nur für db-bezogene Dinge benötigen, unterstützen einige OR) Mapper (z. B. NHibernate) standardmäßig Transactinos.

Es kommt auch darauf an, was Sie brauchen. Für grundlegende SQL-Transaktionen können Sie versuchen, TSQL-Transaktionen mit BEGIN TRANS und COMMIT TRANS in Ihrem Code auszuführen. Das ist der einfachste Weg, hat aber Komplexität und Sie müssen vorsichtig sein, um ein korrektes Commit (und Rollback) durchzuführen.

Ich würde sowas benutzen

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
}

Bei einem Fehler werden Sie direkt aus dem using entfernt und die Transaktion wird immer festgeschrieben oder rückgängig gemacht (je nachdem, was Sie anweisen). Das größte Problem, mit dem wir konfrontiert waren, war sicherzustellen, dass es immer begangen wurde. Die Verwendung stellt sicher, dass der Umfang der Transaktion begrenzt ist.

0
Brody