2008-10-22 6 views
123

Quelles sont les meilleures pratiques pour effectuer des transactions en C# .Net 2.0. Quelles sont les classes qui devraient être utilisées? Quels sont les pièges à surveiller, etc. Tous ces trucs de commit et de rollback. Je commence juste un projet où je pourrais devoir faire quelques transactions tout en insérant des données dans la DB. Toutes les réponses ou les liens pour des informations de base sur les transactions sont les bienvenus.Transactions en .net

+0

Voici un bon exemple de [Transactions dans .NET] (http://www.codeproject.com/KB/database/transactions.aspx) sur codeproject à utiliser comme un début. –

+2

Utile http://www.codeproject.com/Articles/690136/All-About-TransactionScope – Kiquenet

Répondre

235

Il existe deux principaux types de transactions; transactions de connexion et transactions ambiantes. Une transaction de connexion (telle que SqlTransaction) est liée directement à la connexion db (telle que SqlConnection), ce qui signifie que vous devez continuer à faire passer la connexion - OK dans certains cas, mais ne permet pas "create/use/release" utilisation, et ne permet pas le travail cross-db. Un exemple (formaté pour l'espace):

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

Pas trop en désordre, mais limité à notre connexion "conn". Si nous voulons appeler à différentes méthodes, nous devons maintenant passer "conn" autour.

L'alternative est une transaction ambiante; nouveau dans .NET 2.0, l'objet TransactionScope (System.Transactions.dll) permet une utilisation sur une plage d'opérations (les fournisseurs appropriés s'enrôleront automatiquement dans la transaction ambiante). Cela facilite le réintégration dans le code existant (non transactionnel) et la possibilité de parler à plusieurs fournisseurs (bien que DTC soit impliqué si vous en parlez à plus d'un).

Par exemple:

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

Notez ici que les deux méthodes peuvent gérer leurs propres connexions (ouvert/utilisation/fermer/éliminer), mais ils deviendront en silence une partie de la transaction ambiante sans nous avoir à passer quoi que ce soit.

Si vos erreurs de code, Dispose() seront appelées sans Complete(), elles seront annulées. L'imbrication attendue, etc., est prise en charge, bien que vous ne puissiez pas annuler une transaction interne tout en complétant la transaction externe: si quelqu'un n'est pas satisfait, la transaction est annulée.

L'autre avantage de TransactionScope est qu'il n'est pas lié uniquement aux bases de données; tout fournisseur conscient de la transaction peut l'utiliser. WCF, par exemple. Ou il y a même des modèles d'objets compatibles avec TransactionScope (c'est-à-dire des classes .NET avec possibilité de restauration - peut-être plus facile qu'un souvenir, bien que je n'ai jamais utilisé cette approche moi-même).

Dans l'ensemble, un objet très, très utile.

Quelques mises en garde:

  • Sur SQL Server 2000, un TransactionScope ira à DTC immédiatement; Ceci est corrigé dans SQL Server 2005 et au-dessus, il peut utiliser le LTM (beaucoup moins de frais généraux) jusqu'à ce que vous parliez à 2 sources etc, quand il est élevé à DTC.
  • Il y a un glitch cela signifie que vous pourriez avoir besoin de modifier votre chaîne de connexion
+1

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

+0

CSLA .NET 2.0 prend en charge l'objet TransactionScope! –

+0

Le problème ici est lorsque vous avez une transaction dans la première méthode et cette méthode (encapsulation) ne sait pas si elle sera appelée à partir d'une transaction parente ou non. –

1

Si vous en avez juste besoin pour des éléments liés à la base de données, certains OR Mappers (par exemple NHibernate) prennent en charge les transactions transactinos par défaut.

0

Cela dépend aussi de ce que vous avez besoin. Pour les transactions SQL de base, vous pouvez essayer de faire des transactions TSQL en utilisant BEGIN TRANS et COMMIT TRANS dans votre code. C'est le moyen le plus simple mais il a de la complexité et vous devez faire attention à commettre correctement (et rollback).

J'utiliser quelque chose comme

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 
} 

Tout manquement vous pop à droite de la using et la transaction sera toujours validée ou annulée (selon ce que vous dites à le faire). Le plus gros problème auquel nous avons dû faire face était de nous assurer de toujours nous engager. L'utilisation garantit que la portée de la transaction est limitée.

3

Vous pouvez également placer la transaction dans sa propre procédure stockée et la gérer de cette façon plutôt que d'effectuer elle-même des transactions en C#.

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

Pouvez-vous s'il vous plaît expliquer votre code? –

Questions connexes