Transactions locales

Les transactions dans ADO.NET servent à lier plusieurs tâches ensemble de sorte qu’elles s’exécutent comme une seule unité de travail. Par exemple, imaginez qu'une application effectue deux tâches. Premièrement, elle met à jour une table avec des informations de commande. Deuxièmement, elle met à jour une table qui contient des informations de stock, en débitant les articles commandés. Si l’une ou l’autre des tâches échoue, les deux mises à jour sont annulées.

Détermination du type de transaction

Une transaction est considérée comme locale quand il s’agit d’une transaction monophase et qu’elle est gérée directement par la base de données. Une transaction est considérée comme étant distribuée quand elle est coordonnée par un moniteur de transaction et qu’elle utilise des mécanismes de prévention de défaillance (tels qu’une validation en deux phases) pour sa résolution.

Chacun des fournisseur de données .NET Framework a son propre objet Transaction pour l’exécution des transactions locales. Si vous avez besoin qu’une transaction soit effectuée dans une base de données SQL Server, sélectionnez une transaction System.Data.SqlClient. Pour une transaction Oracle, utilisez le fournisseur System.Data.OracleClient. Par ailleurs, il existe une classe DbTransaction qui permet d’écrire du code indépendant du fournisseur qui exige des transactions.

Notes

Les transactions ont une efficacité maximale quand elles sont exécutées sur le serveur. Si vous utilisez une base de données SQL Server qui utilise beaucoup des transactions explicites, envisagez de les écrire sous la forme de procédures stockées à l’aide de l’instruction Transact-SQL BEGIN TRANSACTION.

Exécution d’une transaction à l’aide d’une connexion unique

Dans ADO.NET, vous contrôlez les transactions avec l’objet Connection. Vous pouvez initier une transaction locale avec la méthode BeginTransaction. Après avoir commencé une transaction, vous pouvez inscrire une commande dans cette transaction avec la propriété Transaction d’un objet Command. Vous pouvez ensuite valider ou annuler les modifications apportées à la source de données en fonction de la réussite ou de l’échec des composants de la transaction.

Notes

La méthode EnlistDistributedTransaction ne doit pas être utilisée pour une transaction locale.

La portée de la transaction est limitée à la connexion. L’exemple suivant exécute une transaction explicite consistant en deux commandes distinctes dans le bloc try. Les commandes exécutent des instructions INSERT sur la table Production.ScrapReason dans l’exemple de base de données SQL Server AdventureWorks, qui sont validées si aucune exception n’est levée. Le code dans le bloc catch annule la transaction en cas d'exception. En cas d'annulation de la transaction ou de fermeture de la connexion avant que la transaction ne soit terminée, celle-ci est automatiquement annulée.

Exemple

Procédez comme suit pour effectuer une transaction.

  1. Appelez la méthode BeginTransaction de l’objet SqlConnection pour marquer le début de la transaction. La méthode BeginTransaction retourne une référence à la transaction. Cette référence est affectée aux objets SqlCommand inscrits dans la transaction.

  2. Assignez l'objet Transaction à la propriété Transaction de l'objet SqlCommand à exécuter. Si une commande est exécutée sur une connexion sur laquelle une transaction est active et si l’objet Transaction n’a pas été affecté à la propriété Transaction de l’objet Command, une exception est levée.

  3. Exécutez les commandes requises.

  4. Appelez la méthode Commit de l'objet SqlTransaction pour effectuer la transaction ou la méthode Rollback pour y mettre fin. Si la connexion est fermée ou libérée avant que l’une des méthodes Commit ou Rollback ait été exécutée, la transaction est annulée.

L’exemple de code suivant montre la logique transactionnelle en utilisant ADO.NET avec Microsoft SQL Server.

using (SqlConnection connection = new(connectionString))
{
    connection.Open();

    // Start a local transaction.
    SqlTransaction sqlTran = connection.BeginTransaction();

    // Enlist a command in the current transaction.
    SqlCommand command = connection.CreateCommand();
    command.Transaction = sqlTran;

    try
    {
        // Execute two separate commands.
        command.CommandText =
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
        command.ExecuteNonQuery();
        command.CommandText =
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
        command.ExecuteNonQuery();

        // Commit the transaction.
        sqlTran.Commit();
        Console.WriteLine("Both records were written to database.");
    }
    catch (Exception ex)
    {
        // Handle the exception if the transaction fails to commit.
        Console.WriteLine(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.
            Console.WriteLine(exRollback.Message);
        }
    }
}
Using connection As New SqlConnection(connectionString)
    connection.Open()

    ' Start a local transaction.
    Dim sqlTran As SqlTransaction = connection.BeginTransaction()

    ' Enlist a command in the current transaction.
    Dim command As SqlCommand = connection.CreateCommand()
    command.Transaction = sqlTran

    Try
        ' Execute two separate commands.
        command.CommandText = _
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')"
        command.ExecuteNonQuery()
        command.CommandText = _
          "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')"
        command.ExecuteNonQuery()

        ' Commit the transaction
        sqlTran.Commit()
        Console.WriteLine("Both records were written to database.")

    Catch ex As Exception
        ' Handle the exception if the transaction fails to commit.
        Console.WriteLine(ex.Message)

        Try
            ' Attempt to roll back the transaction.
            sqlTran.Rollback()

        Catch exRollback As Exception
            ' Throws an InvalidOperationException if the connection 
            ' is closed or the transaction has already been rolled 
            ' back on the server.
            Console.WriteLine(exRollback.Message)
        End Try
    End Try
End Using

Voir aussi