HOW TO:管理 Entity Framework 中的交易

本主題提供的範例將示範如何定義交易,以便協調使用其他外部作業對物件內容中的物件進行變更。 如需詳細資訊,請參閱管理連接和交易 (Entity Framework)

本主題的範例是根據 AdventureWorks 銷售模型。 若要執行此範例中的程式碼,您必須已經將 AdventureWorks Sales Model 加入到專案中,並設定您的專案使用 Entity Framework。 若要這樣做,請完成 HOW TO:使用實體資料模型精靈 (Entity Framework) 中的程序。 您也必須安裝 Microsoft Windows Message Queuing。

範例

此範例會定義 TransactionScopeTransactionScope 可確保對物件內容中之物件所做的變更會以訊息佇列進行協調。 當 Entity Framework 將變更儲存至資料庫時,它就會使用這個交易。 發生 UpdateException 時,最多會重試兩次作業。 當作業成功時,系統就會接受物件內容中的變更。 如需詳細資訊,請參閱管理連接和交易 (Entity Framework)

這則範例會使用長時間執行的物件內容,而系統會在交易成功或所有重試作業都已經嘗試過之後處置 (Dispose) 此物件內容。

Imports System
Imports System.Linq
Imports System.Data
Imports System.Data.Objects
Imports System.Messaging
Imports System.Transactions

Class TransactionSample
    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 New AdventureWorksEntities()

        Dim success As Boolean = False

        ' Wrap the operation in a retry loop. 
        For i As Integer = 0 To retries - 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 = (From o In context.SalesOrderHeaders _
                        Where o.SalesOrderID = orderId _
                        Select o).First()

                    ' Load items for the order, if not already loaded. 
                    ' Do this if the lazy loading is turned off.
                    If Not order.SalesOrderDetails.IsLoaded Then
                        order.SalesOrderDetails.Load()
                    End If

                    ' Load the customer, if not already loaded. 
                    ' Do this if the lazy loading is turned off.
                    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(), DateTime.Today)

                    ' Add new item to the order. 
                    order.SalesOrderDetails.Add(newItem)

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

                    ' 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))

                        ' Send the message to the queue. 
                        q.Send(msg)
                    End Using

                    ' Mark the transaction as complete. 
                    transaction.Complete()
                    success = True
                    Exit Try
                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 ex.[GetType]() <> GetType(UpdateException) Then
                        Console.WriteLine(("An error occured. " & "The operation cannot be retried.") + ex.Message)
                        Exit Try
                        ' If we get to this point, the operation will be retried. 
                    End If
                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 & " tries.")
        End If

        ' Dispose the object context. 
        context.Dispose()
    End Sub
End Class
using System;
using System.Linq;
using System.Data;
using System.Data.Objects;
using System.Messaging;
using System.Transactions;

namespace ObjectServicesConceptsCS
{
    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.SalesOrderHeaders.Where
                        ("it.SalesOrderID = @id", new ObjectParameter(
                         "id", orderId)).First();

                        // Load items for the order, if not already loaded.
                        if (!order.SalesOrderDetails.IsLoaded)
                        {
                            order.SalesOrderDetails.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.SalesOrderDetails.Add(newItem);

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

                        // 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();
        }
    }
}

另請參閱

概念

管理連接和交易 (Entity Framework)