Question

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 validation et d'annulation. Je commence juste un projet où je pourrais avoir besoin de faire des transactions tout en insérant des données dans la base de données. Toutes les réponses ou les liens pour des informations de base sur les transactions sont les bienvenus.

Était-ce utile?

La solution

Il existe 2 principaux types de transactions; transactions de connexion et transactions ambiantes. Une transaction de connexion (telle que SqlTransaction) est directement liée à la connexion à la base de données (telle que SqlConnection), ce qui signifie que vous devez continuer à passer la connexion - OK dans certains cas, mais n'autorisez pas "créer / utiliser / libérer". ; 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 brouillon, mais limité à notre connexion "conn". Si nous voulons faire appel à différentes méthodes, nous devons maintenant passer le mot-clé "conn". autour.

L’alternative est une transaction ambiante; nouveauté .NET 2.0, l’objet TransactionScope (Système .Transactions.dll) permet une utilisation sur une gamme d'opérations (des fournisseurs appropriés seront automatiquement inscrits dans la transaction ambiante). Cela facilite la réintégration dans le code existant (non transactionnel) et la possibilité de parler à plusieurs fournisseurs (bien que DTC soit impliqué si vous 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 (open / use / close / dispose), mais qu'elles feront désormais partie intégrante de la transaction ambiante sans que nous ayons à passer quoi que ce soit.

Si votre code est erroné, Dispose () sera appelé sans Complete (), il sera donc annulé. 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 abandonnée.

L’autre avantage de TransactionScope est qu’il n’est pas uniquement lié aux bases de données; tout fournisseur sensible aux transactions peut l'utiliser. WCF, par exemple. Vous pouvez également utiliser des modèles d’objets compatibles avec TransactionScope (par exemple, les classes .NET avec possibilité de restauration - peut-être plus facile que les souvenirs, même si je n’ai jamais utilisé cette approche moi-même).

Tout compte fait, un objet très utile.

Quelques mises en garde:

  • Sur SQL Server 2000, un TransactionScope ira immédiatement vers DTC; cela est résolu dans SQL Server 2005 et versions supérieures, il peut utiliser le LTM (beaucoup moins de temps système) jusqu’à ce que vous parliez à 2 sources, etc., quand il est élevé au DTC.
  • Il existe un pépin qui signifie que vous devrez peut-être modifier votre chaîne de connexion

Autres conseils

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;

               }
           }
       }


   }

Vous pouvez également encapsuler la transaction dans sa propre procédure stockée et la gérer de cette façon au lieu d'effectuer des transactions en C # lui-même.

si vous en avez simplement besoin pour les éléments liés à la base de données, certains mappeurs OR (NHibernate, par exemple) prennent en charge les transactions par défaut.

Cela dépend aussi de ce dont 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 la méthode la plus simple, mais elle est complexe et vous devez faire attention à la commettre correctement (et à la restauration).

Je voudrais 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 échec vous échappera du code en utilisant et la transaction sera toujours validée ou annulée (selon ce que vous lui indiquez de faire). Le plus gros problème auquel nous avons été confrontés a été de nous assurer qu’il était toujours engagé. L'utilisation garantit que la portée de la transaction est limitée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top