2008-10-22 4 views
123

Was sind die besten Vorgehensweisen für Transaktionen in C# .Net 2.0? Welche Klassen sollten verwendet werden? Was sind die Fallstricke, nach denen man Ausschau halten muss usw. All das Commit- und Rollback-Zeug. Ich beginne gerade ein Projekt, wo ich einige Transaktionen machen muss, während ich Daten in die Datenbank einfüge. Alle Antworten oder Links für selbst grundlegende Dinge über Transaktionen sind willkommen.Transaktionen in .net

+0

Hier ist ein gutes Beispiel für [Transaktionen in .NET] (http://www.codeproject.com/KB/database/transactions.aspx) auf Codeprojekt als Start zu verwenden. –

+2

Nützlich http://www.codeproject.com/Articles/690136/All-About-TransactionScope – Kiquenet

Antwort

235

Es gibt 2 Hauptarten von Transaktionen; Verbindungstransaktionen und Ambient-Transaktionen. Eine Verbindungstransaktion (z. B. SqlTransaction) ist direkt an die db-Verbindung gebunden (z. B. SqlConnection), was bedeutet, dass Sie die Verbindung weiterleiten müssen - in einigen Fällen OK, aber nicht zulassen/erstellen/verwenden/freigeben Verwendung, und Cross-db-Arbeit nicht zulassen. Ein Beispiel (für den Raum formatiert):

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

Nicht zu chaotisch, aber begrenzt auf unsere Verbindung "conn". Wenn wir zu verschiedenen Methoden aufrufen wollen, müssen wir jetzt "Conn" weitergeben.

Die Alternative ist eine Ambient-Transaktion; Neu in .NET 2.0 ermöglicht das Objekt TransactionScope (System.Transactions.dll) die Verwendung über eine Reihe von Operationen (geeignete Anbieter werden automatisch in die Ambient-Transaktion aufgenommen). Dies macht es einfach, sich in vorhandenen (nicht-transaktionalen) Code einzufügen und mit mehreren Anbietern zu kommunizieren (obwohl DTC involviert wird, wenn Sie mit mehr als einem sprechen).

Zum Beispiel:

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

Hinweis hier, dass die beiden Methoden, um ihre eigenen Verbindungen verarbeiten kann (offen/Nutzung/close/dispose), doch werden sie leise Teil der Ambient-Transaktion werden ohne uns passieren müssen zu alles in.

Wenn Ihre Codefehler, Dispose() ohne Complete() aufgerufen wird, wird es zurückgesetzt. Die erwartete Verschachtelung usw. wird unterstützt, obwohl Sie eine innere Transaktion nicht zurücksetzen können, ohne die äußere Transaktion abzuschließen: Wenn jemand unglücklich 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 - vielleicht einfacher als ein Memento, obwohl ich diesen Ansatz nie selbst benutzt habe).

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

Einige Einschränkungen:

  • auf SQL Server 2000, eine Transaction zu DTC sofort gehen wird; Dies ist in SQL Server 2005 und höher behoben, es kann den LTM (viel weniger Overhead) verwenden, bis Sie mit 2 Quellen usw. sprechen, wenn es auf DTC erhöht wird.
  • Es gibt eine glitch das heißt, Sie Ihre Verbindungszeichenfolge
+1

http://www.codeguru.com/columns/vb/article.php/c11067 – Kimoz

+0

CSLA .NET 2.0 unterstützt TransactionScope-Objekt! –

+0

Das Problem hier ist, wenn Sie eine Transaktion in der ersten Methode haben und diese Methode (Kapselung) nicht weiß, ob von einer übergeordneten Transaktion oder nicht aufgerufen wird. –

1

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

0

zwicken müssen eventuell Es hängt auch davon ab, was Sie brauchen. Für grundlegende SQL-Transaktionen können Sie TSQL-Transaktionen versuchen, indem Sie BEGIN TRANS und COMMIT TRANS in Ihrem Code verwenden. Das ist der einfachste Weg, aber es hat Komplexität und Sie müssen vorsichtig sein, um korrekt zu committen (und Rollback).

würde ich so etwas wie

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 
} 

verwenden Jeder Fehler werden Sie direkt aus dem using Pop und die Transaktion wird immer Commit oder Rollback (je nachdem, was Sie sagen, es zu tun). Das größte Problem, dem wir gegenüberstanden, bestand darin, dafür zu sorgen, dass es immer eingehalten wurde. Die Verwendung stellt sicher, dass der Umfang der Transaktion begrenzt ist.

3

Sie können die Transaktion auch in ihre eigene gespeicherte Prozedur einfügen und so behandeln, anstatt Transaktionen in C# selbst auszuführen.

10
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; 

       } 
      } 
     } 


    } 
+8

Können Sie bitte Ihren Code erklären? –