방법: 개체 서비스 트랜잭션 관리(Entity Framework)
이 항목에서는 다른 외부 작업을 사용하여 개체 컨텍스트의 개체에 대한 변경 작업을 조정하는 트랜잭션을 정의하는 방법에 대한 예제를 제공합니다. 자세한 내용은 개체 서비스에서 트랜잭션 관리(Entity Framework)를 참조하십시오.
이 항목의 예제는 AdventureWorks Sales 모델(EDM)을 기반으로 합니다. 이 예제의 코드를 실행하려면 프로젝트에 AdventureWorks Sales 모델을 추가하고 Entity Framework를 사용하도록 프로젝트를 구성해야 합니다. 이렇게 하려면 방법: 엔터티 데이터 모델 마법사 사용(Entity Framework)의 절차를 수행합니다. 또한 Microsoft Windows Message Queuing이 설치되어 있어야 합니다.
예제
이 예제에서는 TransactionScope를 정의합니다. TransactionScope를 정의하면 개체 컨텍스트의 개체에 대한 변경 내용이 메시지 큐에 따라 조정됩니다. 개체 서비스는 데이터베이스에 변경 내용을 저장할 때 이 트랜잭션을 사용합니다. UpdateException이 발생하면 작업이 최대 두 번까지 다시 시도됩니다. 작업이 완료되면 개체 컨텍스트의 변경 내용이 승인됩니다. 자세한 내용은 개체 서비스에서 트랜잭션 관리(Entity Framework)를 참조하십시오.
이 예제에서는 트랜잭션이 완료되거나 모든 재시도가 시도된 후 제거되는 장기 실행 개체 컨텍스트를 사용합니다.
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();
}
}
}
참고 항목
기타 리소스
How to: Manage EntityClient Transactions (Entity Framework)
How to: Explicitly Manage EntityClient Transactions Using EntityTransaction (Entity Framework)
연결 및 트랜잭션 관리(Entity Framework 작업)