2009-05-26 10 views
7

Dans mon application Web, je dois vérifier les actions de l'utilisateur. Donc, chaque fois que l'utilisateur entreprend une action, je mets à jour l'objet sur lequel l'action est effectuée et je garde une trace d'audit de cette action.Utilisation de transactions avec subsonic

Maintenant Si je modifie d'abord l'objet puis que je mets à jour la piste d'audit mais que la piste d'audit échoue, alors quoi?

De toute évidence, je dois annuler les modifications apportées à l'objet modifié. Je peux utiliser Sql-Transactions dans une application simple, mais j'utilise Subsonic pour parler à db. Comment je peux gérer la situation?

Répondre

10

Quelque chose comme:

Using ts As New System.Transactions.TransactionScope() 
    Using sharedConnectionScope As New SubSonic.SharedDbConnectionScope() 

' Do your individual saves here 

' If all OK 
     ts.Complete() 

    End Using 
End Using 
+1

Je peux confirmer que TransactionScope fonctionne correctement avec SubSonic et effectue correctement les transactions de restauration. – kd7

+0

Merci @kevinw et @bnkdev. J'utilise C# donc je posterai le code en C# aussi afin qu'il puisse être facilement utilisé par d'autres. Aussi ne mettriez-vous pas les sauvegardes individuelles ou les actions à l'intérieur de try/catch donc il est plus facile de savoir si tout est OK ou non? – TheVillageIdiot

14

La answer donnée par @Kevinw est tout à fait correct. Je poste ceci juste comme la traduction de sa réponse au code C#. Je n'utilise pas de commentaires car il ne formatera pas le code :) Aussi, j'utilise try/catch pour savoir si la transaction devrait être terminée ou être annulée.

using (System.Transactions.TransactionScope ts = new TransactionScope()) 
{ 
    using (SharedDbConnectionScope scs = new SharedDbConnectionScope()) 
    { 
     try 
     { 
      //do your stuff like saving multiple objects etc. here 

      //everything should be completed nicely before you reach this 
      //line if not throw exception and don't reach to line below 
      ts.Complete(); 
     } 
     catch (Exception ex) 
     { 
      //ts.Dispose(); //Don't need this as using will take care of it. 
      //Do stuff with exception or throw it to caller 
     } 
    } 
} 
+1

L'appel de 'ts.Dispose()' à l'intérieur de la catch-clause n'est pas nécessaire car l'instruction using s'en chargera de toute façon. Dans le cas général, il pourrait même causer des problèmes car '' SharedDbConnectionScope'' ou tout autre code prenant en charge les transactions lancé dans la portée de la transaction pourrait dépendre d'être éliminé avant que la portée de la transaction englobante ne soit éliminée. –

+0

@OskarBerggren l'a commenté. – TheVillageIdiot

1

Nope. Si je mets le SharedDbConnectionScope à l'extérieur les changements sont visibles dans la base de données avant ts.Complete(). Le placer à l'intérieur bloque le serveur jusqu'à ce que l'opération soit terminée.