140 votes

Transactions en .net

Quelles sont les meilleures pratiques pour effectuer des transactions dans C # .Net 2.0. Quelles sont les classes à utiliser? Quels sont les pièges à surveiller, etc. Je commence juste un projet où je pourrais avoir besoin de faire des transactions en insérant des données dans la base de données. Toutes les réponses ou tous les liens pour des informations de base sur les transactions sont les bienvenus.

262voto

Marc Gravell Points 482669

Il existe 2 principaux types de transactions; connexion transactions et la température ambiante transactions. Une connexion transaction (tels que SqlTransaction) est directement liée à l'id de connexion (comme SqlConnection), ce qui signifie que vous devez avoir passer le lien autour - OK, dans certains cas, mais ne permet pas de "créer/utiliser/release" d'utilisation, et ne pas permettre à la croix-db de travail. Un exemple (formaté pour l'espace):

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

Pas trop salissant, mais limité à notre connexion "conn". Si nous voulons faire appel à différentes méthodes, nous avons maintenant besoin de passer "conn" autour de.

L'alternative est une ambiante de transaction; de nouvelles .NET 2.0, le TransactionScope objet (System.Transactions.dll) permet l'utilisation d'une gamme d'opérations (adapté de fournisseurs seront automatiquement s'enrôler dans l'ambiance de la transaction). Cela le rend facile à intégrer dans l'existant (non-transactionnelle) du code, et de parler à de multiples fournisseurs (même si DTC de s'impliquer si vous parlez plus d'un).

Par exemple:

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

À noter ici que les deux méthodes permettent de gérer leurs propres connexions (ouvrir/utilisation/fermer/jeter), mais ils en silence à devenir une partie de l'air ambiant, transaction sans avoir à passer n'importe quoi.

Si votre code d'erreurs, d'en Disposer() sera appelée sans Remplir(), de sorte qu'il sera annulée. L'imbrication attendue etc est pris en charge, bien que vous ne pouvez pas revenir intérieure de la transaction encore compléter la transaction externe: si quelqu'un est malheureux, la transaction est annulée.

L'autre avantage de TransactionScope est qu'il n'est pas lié seulement à des bases de données; tout compte des transactions, le fournisseur peut utiliser. WCF, par exemple. Ou il y a encore quelques TransactionScope compatible avec les modèles d'objet autour (c'est à dire .NET des classes avec une capacité 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 très, très utile de l'objet.

Quelques mises en garde:

  • Sur SQL Server 2000, un TransactionScope va aller à la DTC immédiatement; c'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 parlez de 2 sources, etc, quand il est élevé à la DTC.
  • Il y a un glitch qui signifie que vous pourriez avoir besoin de modifier le son de votre chaîne de connexion

11voto

Ali Gholizadeh Points 39
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;

               }
           }
       }


   }

3voto

Charles Graham Points 8132

Vous pouvez également placer la transaction dans sa propre procédure stockée et la gérer de cette manière au lieu d'effectuer des transactions dans C # elle-même.

1voto

si vous en avez juste besoin pour des choses liées à la base de données, certains Mappeurs OR (par exemple NHibernate) prennent en charge les transactinos par défaut.

0voto

Brody Points 1859

Il dépend de ce que vous avez besoin. Pour SQL de base transactions que vous pourriez essayer de faire TSQL des transactions en utilisant de COMMENCER TRANS et de COMMETTRE des TRANS dans votre code. C'est la plus facile, mais il n'ont complexité et vous devez être prudent afin d'engager correctement (et de 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 manquement sera pop droit de l'aide et de l'trasnaction toujours commit ou rollback (selon ce que vous lui dites de faire). Le plus gros problème que nous avons été confrontés a été de s'assurer qu'il engage toujours. L'utilisation de assure le champ d'application de l'opération est limitée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X