WS 트랜잭션 흐름
TransactionFlow 샘플 WS-Atomic Transaction 또는 OleTransactions 프로토콜을 사용하여 클라이언트 조정 트랜잭션 및 트랜잭션 흐름에 대한 클라이언트 및 서버 옵션을 사용하는 방법을 보여 줍니다. 이 샘플은 계산기 서비스를 구현하는 시작을 기반으로 하지만, 작업은 TransactionFlowOption 열거형과 함께 TransactionFlowAttribute
를 사용하여 트랜잭션 흐름이 어느 정도로 활성화되는지를 보여주기 위해 설정됩니다. 흐름된 트랜잭션의 범위 내에서 요청된 작업의 로그는 데이터베이스에 기록되고 클라이언트 조정 트랜잭션이 완료될 때까지 유지됩니다. 클라이언트 트랜잭션이 완료되지 않으면 웹 서비스 트랜잭션은 데이터베이스에 대한 적절한 업데이트가 커밋되지 않도록 합니다.
메모
이 샘플에 대한 설치 절차 및 빌드 지침은 이 항목의 끝에 있습니다.
서비스 및 트랜잭션에 대한 연결을 시작한 후 클라이언트는 여러 서비스 작업에 액세스합니다. 서비스에 대한 계약은 각 작업이 TransactionFlowOption
에 대해 다른 설정을 보여주는 방식으로 다음과 같이 정의됩니다.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
double Add(double n1, double n2);
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
double Subtract(double n1, double n2);
[OperationContract]
[TransactionFlow(TransactionFlowOption.NotAllowed)]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
}
처리할 순서대로 작업을 정의합니다.
Add
작업 요청에는 흐름된 트랜잭션이 포함되어야 합니다.Subtract
작업 요청에는 흐름된 트랜잭션이 포함될 수 있습니다.Multiply
작업 요청에 명시적 NotAllowed 설정을 통해 흐르는 트랜잭션을 포함해서는 안 됩니다.Divide
작업 요청에는TransactionFlow
특성을 생략하여 흐름된 트랜잭션을 포함해서는 안 됩니다.
트랜잭션 흐름을 사용하도록 설정하려면 적절한 작업 특성 외에도 <transactionFlow> 속성을 사용하는 바인딩을 사용해야 합니다. 이 샘플에서 서비스의 구성은 메타데이터 Exchange 엔드포인트 외에도 TCP 엔드포인트 및 HTTP 엔드포인트를 노출합니다. TCP 엔드포인트와 HTTP 엔드포인트는 <transactionFlow> 속성을 사용하도록 설정된 다음 바인딩을 사용합니다.
<bindings>
<netTcpBinding>
<binding name="transactionalOleTransactionsTcpBinding"
transactionFlow="true"
transactionProtocol="OleTransactions"/>
</netTcpBinding>
<wsHttpBinding>
<binding name="transactionalWsatHttpBinding"
transactionFlow="true" />
</wsHttpBinding>
</bindings>
메모
시스템 제공 netTcpBinding은 transactionProtocol의 사양을 허용하는 반면, 시스템 제공 wsHttpBinding은 상호 운용 가능한 WSAtomicTransactionOctober2004 프로토콜만 사용합니다. OleTransactions 프로토콜은 WCF(Windows Communication Foundation) 클라이언트에서만 사용할 수 있습니다.
ICalculator
인터페이스를 구현하는 클래스의 경우, 모든 메서드는 true
로 설정된 TransactionScopeRequired 속성을 가집니다. 이 설정은 메서드 내에서 수행된 모든 작업이 트랜잭션 범위 내에서 발생한다는 것을 선언합니다. 이 경우 수행된 작업에는 로그 데이터베이스에 대한 기록이 포함됩니다. 작업 요청에 흐름된 트랜잭션이 포함된 경우 들어오는 트랜잭션의 범위 내에서 작업이 발생하거나 새 트랜잭션 범위가 자동으로 생성됩니다.
메모
TransactionScopeRequired 속성은 서비스 메서드 구현에 대한 로컬 동작을 정의하며 트랜잭션 흐름에 대한 클라이언트의 기능 또는 요구 사항을 정의하지 않습니다.
// Service class that implements the service contract.
[ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable)]
public class CalculatorService : ICalculator
{
[OperationBehavior(TransactionScopeRequired = true)]
public double Add(double n1, double n2)
{
RecordToLog(String.Format(CultureInfo.CurrentCulture, "Adding {0} to {1}", n1, n2));
return n1 + n2;
}
[OperationBehavior(TransactionScopeRequired = true)]
public double Subtract(double n1, double n2)
{
RecordToLog(String.Format(CultureInfo.CurrentCulture, "Subtracting {0} from {1}", n2, n1));
return n1 - n2;
}
[OperationBehavior(TransactionScopeRequired = true)]
public double Multiply(double n1, double n2)
{
RecordToLog(String.Format(CultureInfo.CurrentCulture, "Multiplying {0} by {1}", n1, n2));
return n1 * n2;
}
[OperationBehavior(TransactionScopeRequired = true)]
public double Divide(double n1, double n2)
{
RecordToLog(String.Format(CultureInfo.CurrentCulture, "Dividing {0} by {1}", n1, n2));
return n1 / n2;
}
// Logging method omitted for brevity
}
클라이언트에서 작업에 대한 서비스의 TransactionFlowOption
설정은 클라이언트에서 생성된 ICalculator
인터페이스 정의에 반영됩니다. 또한 서비스의 transactionFlow
속성 설정은 클라이언트의 애플리케이션 구성에 반영됩니다. 클라이언트는 적절한 endpointConfigurationName
선택하여 전송 및 프로토콜을 선택할 수 있습니다.
// Create a client using either wsat or oletx endpoint configurations
CalculatorClient client = new CalculatorClient("WSAtomicTransaction_endpoint");
// CalculatorClient client = new CalculatorClient("OleTransactions_endpoint");
메모
이 샘플의 관찰된 동작은 어떤 프로토콜 또는 전송을 선택하든 동일합니다.
서비스에 대한 연결을 시작한 후 클라이언트는 서비스 작업에 대한 호출을 중심으로 새 TransactionScope
만듭니다.
// Start a transaction scope
using (TransactionScope tx =
new TransactionScope(TransactionScopeOption.RequiresNew))
{
Console.WriteLine("Starting transaction");
// Call the Add service operation
// - generatedClient will flow the required active transaction
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine(" Add({0},{1}) = {2}", value1, value2, result);
// Call the Subtract service operation
// - generatedClient will flow the allowed active transaction
value1 = 145.00D;
value2 = 76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine(" Subtract({0},{1}) = {2}", value1, value2, result);
// Start a transaction scope that suppresses the current transaction
using (TransactionScope txSuppress =
new TransactionScope(TransactionScopeOption.Suppress))
{
// Call the Subtract service operation
// - the active transaction is suppressed from the generatedClient
// and no transaction will flow
value1 = 21.05D;
value2 = 42.16D;
result = client.Subtract(value1, value2);
Console.WriteLine(" Subtract({0},{1}) = {2}", value1, value2, result);
// Complete the suppressed scope
txSuppress.Complete();
}
// Call the Multiply service operation
// - generatedClient will not flow the active transaction
value1 = 9.00D;
value2 = 81.25D;
result = client.Multiply(value1, value2);
Console.WriteLine(" Multiply({0},{1}) = {2}", value1, value2, result);
// Call the Divide service operation.
// - generatedClient will not flow the active transaction
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine(" Divide({0},{1}) = {2}", value1, value2, result);
// Complete the transaction scope
Console.WriteLine(" Completing transaction");
tx.Complete();
}
Console.WriteLine("Transaction committed");
작업에 대한 호출은 다음과 같습니다.
Add
요청은 필요한 트랜잭션을 서비스로 전달하고 서비스의 작업은 클라이언트 트랜잭션 범위 내에서 발생합니다.또한 첫 번째
Subtract
요청은 허용된 트랜잭션을 서비스로 전달하고 다시 서비스의 작업은 클라이언트 트랜잭션 범위 내에서 발생합니다.두 번째
Subtract
요청은TransactionScopeOption.Suppress
옵션으로 선언된 새 트랜잭션 범위 내에서 수행됩니다. 이렇게 하면 클라이언트의 초기 외부 트랜잭션이 표시되지 않으며 요청이 트랜잭션을 서비스로 전달하지 않습니다. 이 방법을 사용하면 클라이언트가 필요하지 않은 경우 명시적으로 옵트아웃하고 트랜잭션을 서비스로 전달하지 않도록 보호할 수 있습니다. 서비스의 작업은 연결되지 않은 새 트랜잭션의 범위 내에서 발생합니다.Multiply
요청은 클라이언트가 생성한ICalculator
인터페이스 정의에 TransactionFlowOptionNotAllowed
로 설정된 TransactionFlowAttribute가 포함되어 있기 때문에 트랜잭션을 서비스로 흐르지 않습니다.클라이언트에서 생성된
ICalculator
인터페이스 정의에TransactionFlowAttribute
포함되지 않으므로Divide
요청은 트랜잭션을 서비스로 전달하지 않습니다. 서비스의 작업은 연결되지 않은 다른 새 트랜잭션의 범위 내에서 다시 발생합니다.
샘플을 실행하면 작업 요청 및 응답이 클라이언트 콘솔 창에 표시됩니다. 클라이언트 창에서 Enter 키를 눌러 클라이언트를 종료합니다.
Starting transaction
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Subtract(21.05,42.16) = -21.11
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Completing transaction
Transaction committed
Press <ENTER> to terminate client.
서비스 작업 요청의 로깅은 서비스의 콘솔 창에 표시됩니다. 클라이언트 창에서 Enter 키를 눌러 클라이언트를 종료합니다.
Press <ENTER> to terminate the service.
Writing row to database: Adding 100 to 15.99
Writing row to database: Subtracting 76.54 from 145
Writing row to database: Subtracting 42.16 from 21.05
Writing row to database: Multiplying 9 by 81.25
Writing row to database: Dividing 22 by 7
성공적으로 실행되면 클라이언트의 트랜잭션 범위가 완료되고 해당 범위 내에서 수행된 모든 작업이 커밋됩니다. 특히 언급된 5개의 레코드는 서비스의 데이터베이스에 유지됩니다. 이 중 처음 2개는 클라이언트 트랜잭션 범위 내에서 발생했습니다.
클라이언트의 TransactionScope
내에서 예외가 발생한 경우 트랜잭션을 완료할 수 없습니다. 이렇게 하면 해당 범위 내에 기록된 레코드가 데이터베이스에 커밋되지 않습니다. 이 효과는 외부 TransactionScope
를 완료하라는 호출을 주석 처리하고 나서 샘플 실행을 반복해봄으로써 관찰할 수 있습니다. 이러한 실행에서는 클라이언트 트랜잭션이 해당 작업으로 전달되지 않았기 때문에 마지막 3개 작업(두 번째 Subtract
, Multiply
및 Divide
요청)만 기록됩니다.
샘플을 설정, 빌드 및 실행하려면
C# 또는 Visual Basic .NET 버전의 솔루션을 빌드하려면 Windows Communication Foundation 샘플빌드의 지침을 따릅니다.
SQL Server Express Edition 또는 SQL Server를 설치했으며 연결 문자열이 서비스의 애플리케이션 구성 파일에 올바르게 설정되었는지 확인합니다. 데이터베이스를 사용하지 않고 샘플을 실행하려면 서비스의 애플리케이션 구성 파일에서
usingSql
값을false
설정합니다.단일 또는 컴퓨터 간 구성에서 샘플을 실행하려면 Windows Communication Foundation 샘플실행의 지침을 따릅니다.
메모
컴퓨터 간 구성의 경우 아래 지침을 사용하여 Distributed Transaction Coordinator를 사용하도록 설정하고 Windows SDK의 WsatConfig.exe 도구를 사용하여 WCF 트랜잭션 네트워크 지원을 사용하도록 설정합니다. WsatConfig.exe설정에 대한 자세한 내용은 WS-Atomic 트랜잭션 지원구성을 참조하세요.
동일한 컴퓨터 또는 다른 컴퓨터에서 샘플을 실행하든지 간에 네트워크 트랜잭션 흐름을 사용하도록 MSDTC(Microsoft Distributed Transaction Coordinator)를 구성하고 WsatConfig.exe 도구를 사용하여 WCF 트랜잭션 네트워크 지원을 사용하도록 설정해야 합니다.
샘플 실행을 지원하도록 MSDTC(Microsoft Distributed Transaction Coordinator)를 구성하려면
Windows Server 2003 또는 Windows XP를 실행하는 서비스 머신에서 다음 지침에 따라 들어오는 네트워크 트랜잭션을 허용하도록 MSDTC를 구성합니다.
시작 메뉴에서 제어판으로 이동한 다음, 관리 도구에서 구성 요소 서비스를 선택하세요.
구성 요소 서비스확장하기. 컴퓨터 폴더를 엽니다.
내 컴퓨터 에서 마우스 오른쪽 버튼을 클릭하고, 속성을선택합니다.
MSDTC 탭에서 보안 구성클릭합니다.
네트워크 DTC 액세스 확인하고 인바운드 허용을.
확인클릭한 다음 예 클릭하여 MSDTC 서비스를 다시 시작합니다.
확인 클릭하여 대화 상자를 닫습니다.
Windows Server 2008 또는 Windows Vista를 실행하는 서비스 머신에서 다음 지침에 따라 들어오는 네트워크 트랜잭션을 허용하도록 MSDTC를 구성합니다.
시작 메뉴에서 제어판으로 이동한 후, 관리 도구, 그리고 구성 요소 서비스로 이동합니다.
구성 요소 서비스확장합니다. 컴퓨터 폴더를 엽니다. 분산 트랜잭션 코디네이터을 선택하십시오.
DTC 코디네이터를 마우스 오른쪽 버튼으로 클릭한 후, 속성을 선택합니다.
보안 탭에서 네트워크 DTC 액세스를 확인하고 인바운드를허용하세요.
확인클릭한 다음 예 클릭하여 MSDTC 서비스를 다시 시작합니다.
확인 클릭하여 대화 상자를 닫습니다.
클라이언트 컴퓨터에서 나가는 네트워크 트랜잭션을 허용하도록 MSDTC를 구성합니다.
시작 메뉴에서
Control Panel
, 그다음 관리 도구, 그리고 구성 요소 서비스로 이동하십시오.내 컴퓨터를 마우스 오른쪽 버튼으로 클릭하고 속성을 선택합니다.
MSDTC 탭에서 보안 구성클릭합니다.
네트워크 DTC 액세스을 확인하고 아웃바운드을 허용하십시오.
확인클릭한 다음 예 클릭하여 MSDTC 서비스를 다시 시작합니다.
확인 클릭하여 대화 상자를 닫습니다.