이 설명서는 보관되지만 유지 되지 않습니다.

방법: Entity Framework에서 트랜잭션 관리

이 항목에서는 다른 외부 작업을 사용하여 개체 컨텍스트의 개체에 대한 변경 작업을 조정하는 트랜잭션을 정의하는 방법에 대한 예제를 제공합니다. 자세한 내용은 연결 및 트랜잭션 관리(Entity Framework)를 참조하십시오.

이 항목의 예제는 AdventureWorks Sales 모델을 기반으로 합니다. 이 예제의 코드를 실행하려면 프로젝트에 AdventureWorks Sales 모델을 추가하고 Entity Framework를 사용하도록 프로젝트를 구성해야 합니다. 이렇게 하려면 방법: 엔터티 데이터 모델 마법사 사용(Entity Framework)의 절차를 수행합니다. 또한 Microsoft Windows Message Queuing이 설치되어 있어야 합니다.

예제

이 예제에서는 TransactionScope를 정의합니다. TransactionScope를 정의하면 개체 컨텍스트의 개체에 대한 변경 내용이 메시지 큐에 따라 조정됩니다. Entity Framework 에서는 데이터베이스에 변경 내용을 저장할 때 이 트랜잭션을 사용합니다. UpdateException이 발생하면 작업이 최대 두 번까지 다시 시도됩니다. 작업이 완료되면 개체 컨텍스트의 변경 내용이 승인됩니다. 자세한 내용은 연결 및 트랜잭션 관리(Entity Framework)를 참조하십시오.

이 예제에서는 트랜잭션이 완료되거나 모든 재시도가 시도된 후 제거되는 장기 실행 개체 컨텍스트를 사용합니다.

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

참고 항목

표시: