Procédure : gérer les transactions Object Services (Entity Framework)

Cette rubrique fournit un exemple de définition d'une transaction qui coordonne l'apport de modification aux objets d'un contexte d'objet avec d'autres opérations externes. Pour plus d'informations, voir Gestion des transactions dans Object Services (Entity Framework).

L'exemple de cette rubrique est basé sur le Modèle de vente AdventureWorks Sales Model (EDM). Pour exécuter le code de cet exemple, vous devez déjà avoir ajouté le modèle de vente AdventureWorks Sales Model à votre projet et configuré ce dernier pour qu'il utilise Entity Framework. Pour ce faire, exécutez la procédure décrite dans Procédure : utiliser l'Assistant Entity Data Model (Entity Framework). Microsoft Windows Message Queuing doit également avoir été installé.

Exemple

Cet exemple définit un objet TransactionScope. TransactionScope assure la coordination avec une file d'attente de messages des modifications apportées aux objets du contexte de l'objet. Object Services utilise cette transaction lorsqu'il enregistre les modifications dans la base de données. Lorsqu'un UpdateException se produit, l'opération est réessayée deux fois au maximum. Lorsque l'opération réussit, les modifications du contexte de l'objet sont acceptées. Pour plus d'informations, voir Gestion des transactions dans Object Services (Entity Framework).

Cet exemple utilise un contexte d'objet long, qui est supprimé lorsque l'opération a réussi ou lorsque toutes les tentatives ont été effectuées.

Option Explicit On
Option Strict On

Imports System
Imports System.Linq
Imports System.Data
Imports System.Data.Objects
Imports System.Messaging
Imports System.Transactions
' Prepend with the root namespace for the project.
Imports AdventureWorksModel
Namespace Microsoft.Samples.Edm
    Public Class TranasctionSample
        Public Shared Sub EnlistTransaction()
            Dim retries As Integer = 3
            Dim queueName As String = ".\Fulfilling"

            ' Define variables that we need to add an item.
            Dim quantity As Short = 2
            Dim productId As Integer = 750
            Dim orderId As Integer = 43680

            ' Define a long-running object context.
            Dim context As AdventureWorksEntities _
                = New AdventureWorksEntities()

            Dim success As Boolean = False

            ' Wrap the operation in a retry loop.
            Dim i As Integer
            For i = 0 To retries - 1 Step i + 1
                ' Define a transaction scope for the operations.
                Using transaction As New TransactionScope()
                    Try

                        ' Define a query that returns a order by order ID.
                        Dim order As SalesOrderHeader = _
                            context.SalesOrderHeader.Where( _
                            "it.SalesOrderID = @id", New ObjectParameter( _
                             "id", orderId)).First()

                        ' Load items for the order, if not already loaded.
                        If Not order.SalesOrderDetail.IsLoaded Then
                            order.SalesOrderDetail.Load()
                        End If

                        ' Load the customer, if not already loaded.
                        If Not order.ContactReference.IsLoaded Then
                            order.ContactReference.Load()
                        End If

                        ' Create a new item for an existing order.
                        Dim newItem As SalesOrderDetail = _
                        SalesOrderDetail.CreateSalesOrderDetail( _
                        0, 0, quantity, productId, 1, 0, 0, 0, Guid.NewGuid(), DateAndTime.Today)
                        
                        'Add new item to the order.
                        order.SalesOrderDetail.Add(newItem)

                        ' Save changes pessimistically. This means that changes 
                        ' must be accepted manually once the transaction succeeds.
                        context.SaveChanges(False)

                        ' Create the message queue if it does not already exist.
                        If Not MessageQueue.Exists(queueName) Then
                            MessageQueue.Create(queueName)
                        End If

                        ' Initiate fulfilling order by sending a message.
                        Using q As New MessageQueue(queueName)
                            Dim msg As New System.Messaging.Message( _
                                String.Format("<order customerId='{0}'>" _
                                              + "<orderLine product='{1}' quantity='{2}' />" _
                                              + "</order>", order.Contact.ContactID, _
                                    newItem.ProductID, newItem.OrderQty))
                            q.Send(msg)
                        End Using

                        ' Mark the transaction as complete.
                        transaction.Complete()
                        success = True
                        Exit For
                    Catch ex As Exception
                        ' Handle errors and deadlocks here and retry if needed.
                        ' Allow an UpdateException to pass through and 
                        ' retry, otherwise stop the execution.
                        If Not TypeOf (ex) Is UpdateException Then
                            Console.WriteLine("An error occured. " _
                                + "The operation cannot be retried." _
                                + ex.Message)
                            Exit Sub
                        End If
                        ' If we get to this point, the operation will be retried.
                    End Try
                End Using
            Next
            If success Then
                ' Reset the context since the operation succeeded.
                context.AcceptAllChanges()
            Else
                Console.WriteLine("The operation could not be completed in " _
                        + retries.ToString + " tries.")
            End If
            ' Dispose the object context.
            context.Dispose()
        End Sub
    End Class
End Namespace
using System;
using System.Linq;
using System.Data;
using System.Data.Objects;
using System.Messaging; 
using System.Transactions; 
using AdventureWorksModel;

namespace Microsoft.Samples.Edm
{
    class TransactionSample
    {
        public static void EnlistTransaction()
        {
            int retries = 3;
            string queueName = @".\Fulfilling";

            // Define variables that we need to add an item.
            short quantity = 2;
            int productId = 750;
            int orderId = 43680;

            // Define a long-running object context.
            AdventureWorksEntities context
                = new AdventureWorksEntities();

            bool success = false;

            // Wrap the operation in a retry loop.
            for (int i = 0; i < retries; i++)
            {
                // Define a transaction scope for the operations.
                using (TransactionScope transaction = new TransactionScope())
                {
                    try
                    {
                        // Define a query that returns a order by order ID.
                        SalesOrderHeader order =
                        context.SalesOrderHeader.Where
                        ("it.SalesOrderID = @id", new ObjectParameter(
                         "id", orderId)).First();

                        // Load items for the order, if not already loaded.
                        if (!order.SalesOrderDetail.IsLoaded)
                        {
                            order.SalesOrderDetail.Load();
                        }

                        // Load the customer, if not already loaded.
                        if (!order.ContactReference.IsLoaded)
                        {
                            order.ContactReference.Load();
                        }

                        // Create a new item for an existing order.
                        SalesOrderDetail newItem = SalesOrderDetail.CreateSalesOrderDetail(
                            0, 0, quantity, productId, 1, 0, 0, 0, Guid.NewGuid(), DateTime.Today);

                        // Add new item to the order.
                        order.SalesOrderDetail.Add(newItem);

                        // Save changes pessimistically. This means that changes 
                        // must be accepted manually once the transaction succeeds.
                        context.SaveChanges(false);

                        // Create the message queue if it does not already exist.
                        if (!MessageQueue.Exists(queueName))
                        {
                            MessageQueue.Create(queueName);
                        }

                        // Initiate fulfilling order by sending a message.
                        using (MessageQueue q = new MessageQueue(queueName))
                        {
                            System.Messaging.Message msg =
                                new System.Messaging.Message(String.Format(
                                    "<order customerId='{0}'>" +
                                    "<orderLine product='{1}' quantity='{2}' />" +
                                    "</order>", order.Contact.ContactID,
                                newItem.ProductID, newItem.OrderQty));

                            // Send the message to the queue.
                            q.Send(msg);
                        }

                        // Mark the transaction as complete.
                        transaction.Complete();
                        success = true;
                        break;
                    }
                    catch (Exception ex)
                    {
                        // Handle errors and deadlocks here and retry if needed.
                        // Allow an UpdateException to pass through and 
                        // retry, otherwise stop the execution.
                        if (ex.GetType() != typeof(UpdateException))
                        {
                            Console.WriteLine("An error occured. "
                                + "The operation cannot be retried."
                                + ex.Message);
                            break;
                        }
                        // If we get to this point, the operation will be retried.
                    }
                }
            }
            if (success)
            {
                // Reset the context since the operation succeeded.
                context.AcceptAllChanges();
            }
            else
            {
                Console.WriteLine("The operation could not be completed in "
                    + retries + " tries.");
            }

            // Dispose the object context.
            context.Dispose();
        }
    }
}

Voir aussi

Autres ressources

How to: Manage EntityClient Transactions (Entity Framework)
How to: Explicitly Manage EntityClient Transactions Using EntityTransaction (Entity Framework)
Gestion des connexions et des transactions (Tâches Entity Framework)