2010-11-19 12 views
0

zu arbeiten Wie verwenden Sie Transaktionen in Ihrem Code?Der übliche Weg, mit Transaktionen in C#

Der alte war guter Weg, so etwas zu tun:

try 
{ 
    IDbTransaction tx = Connection.BeginTransaction(); 
    perform_work1 
    perform_work2 
    perform_work3 
    tx.Commit(); 

} 
catch(DbException) 
{ 
    tx.Rollback(); 
    throw; 
} 

Aber dann merkt man, dass Sie DbExceptin Protokollierung der Software hinzugefügt werden soll, und sollte, ersetzen jeden Anschein von transaktionsbezogenen Code.

Die erste Idee ist somethig ähnlich wie dies zu machen:

public static class SafeCallerProxy 
    { 
     public delegate T ResultativeAction<T>(); 

     public static T ExecuteWithResult<T>(IDbConnection conn, ResultativeAction<T> action) 
     { 
      using(IDbTransaction tx = conn.BeginTransaction()) 
      { 
       try 
       { 
        T result = action(); 
        tx.Commit(); 
        return result; 
       } 
       catch (System.Data.DataException) 
       { 
        tx.Rollback(); 
        throw; 
       } 
      } 
     } 

     public static void ExecuteAction(IDbConnection conn, Action action) 
     { 
      using (IDbTransaction tx = conn.BeginTransaction()) 
      { 
       try 
       { 
        action(); 
        tx.Commit(); 
       } 
       catch (System.Data.DataException) 
       { 
        tx.Rollback(); 
        throw; 
       } 
      } 
     } 
    } 

Nutzung

SafeCallerProxy.ExecuteAction(connection,() => 
{ 
    DoWork1(); 
    DoWork2(); 
    DoWork3(); 
} 
); 

Und ich denke, dass ich hier bin Fahrrad neu zu erfinden. Bitte geben Sie ein Beispiel für einen guten Code, der Transaktionsmechanismus einkapselt,

Sory für mein Englisch.

+0

Das ist eigentlich sehr ähnlich wie ich dieses Problem in der Vergangenheit gelöst habe. –

+0

Warum protokollieren Sie nicht einfach die DataException, wenn Sie die Transaktionen zurücksetzen? – msarchet

+1

Just FYI, es gibt bereits eine 'Func ' Delegat in .NET 3.0, die die gleiche Definition wie Ihre 'ResultativeAction 'Delegat hat. –

Antwort

1

Persönlich verwende ich NHibernate with Spring.NET, die AOP Unterstützung hat, also definiere ich im Grunde in einer externen Konfigurationsdatei, die die Methoden sind, die ich unter einer SQL-Transaktion ausgeführt werden möchte. Dies sind normalerweise meine Service-Methoden, die im Prinzip mehrere Datenzugriffsmethoden aufrufen, die ich in einer einzigen Transaktion ausführen möchte.

Ich denke, dass Transaktionsmanagement eine Querschnittsaufgabe ist und sollte nicht mit dem Datenzugriffscode gemischt werden, da es es verschmutzt. Spring.NET kümmert sich um die Erstellung von Laufzeitproxys und injiziert den richtigen Transaktionscode.

+0

Vielen Dank, ich sollte wirklich ein einfaches Muster betrachten: Wenn Sie etwas hinzufügen möchten, das Dekorator pettern der Methode ähnlich ist, gibt es eine große Chance, dass Sie wirklich AOP simulieren möchten. – v00d00

1

Ich verwende LINQ zu Entitäten, die die Transaktionen für mich behandelt. Ich stelle mir vor, es wäre ziemlich einfach, die automatische Protokollierung mit einer T4-Vorlage hinzuzufügen.

0

Sofern ich mich nicht irre, denke ich, dass Sie davon ausgehen können, dass ein Transaktionsobjekt, das die Schnittstelle IDbTransaction implementiert, ein Rollback durchführt, wenn es vor dem Aufruf der Commit-Methode entsorgt wird. Zugegeben, das ist keine Garantie, aber ich denke, es wäre eine schlechte Umsetzung, wenn sie nicht so umgesetzt würde.

Da ich dein Beispiel einfach wie das folgende schreiben würde:

 using (var tx = connection.BeginTransaction()) 
     { 
      DoWork1(); 
      DoWork2(); 
      DoWork3(); 
      tx.Commit(); 
     } 

wenn ich zu fangen und Datenbank Ausnahmen benötigt, um sich einzuloggen, dann würde ich die gesamte Verwendung von Block in einem try/catch wickeln:

 try 
     { 
      using (var tx = connection.BeginTransaction()) 
      { 
       DoWork1(); 
       DoWork2(); 
       DoWork3(); 
       tx.Commit(); 
      } 
     } 
     catch (DataException ex) 
     { 
      // log ex 
     }