WS-transactiestroom
Het TransactionFlow-voorbeeld toont het gebruik van een door de client gecoördineerde transactie en de client- en serveropties voor transactiestroom met behulp van het protocol WS-Atomic Transaction of OleTransactions. Dit voorbeeld is gebaseerd op de Aan de slag waarmee een rekenmachineservice wordt geïmplementeerd, maar de bewerkingen worden toegeschreven aan het gebruik van de TransactionFlowAttribute
met de opsomming TransactionFlowOption om te bepalen in welke mate transactiestroom is ingeschakeld. Binnen het bereik van de gestroomde transactie wordt een logboek van de aangevraagde bewerkingen naar een database geschreven en bewaard totdat de gecoördineerde clienttransactie is voltooid. Als de clienttransactie niet is voltooid, zorgt de webservicetransactie ervoor dat de juiste updates voor de database niet worden doorgevoerd.
Notitie
De installatieprocedure en build-instructies voor dit voorbeeld bevinden zich aan het einde van dit onderwerp.
Nadat een verbinding met de service en een transactie is gestart, heeft de client toegang tot verschillende servicebewerkingen. Het contract voor de service wordt als volgt gedefinieerd, waarbij elke bewerking een andere instelling voor de TransactionFlowOption
laat zien.
[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);
}
Hiermee definieert u de bewerkingen in de volgorde waarin ze moeten worden verwerkt:
Een
Add
-bewerkingsaanvraag moet een gestroomde transactie bevatten.Een
Subtract
-bewerkingsaanvraag kan een gestroomde transactie bevatten.Een
Multiply
-bewerkingsaanvraag mag geen gestroomde transactie bevatten via de expliciete instelling NotAllowed.Een
Divide
-bewerkingsaanvraag mag geen gestroomde transactie bevatten door het weglaten van eenTransactionFlow
kenmerk.
Als u transactiestroom wilt inschakelen, moeten bindingen met de <transactionFlow>-eigenschap worden gebruikt, naast de juiste bewerkingskenmerken. In dit voorbeeld maakt de configuratie van de service een TCP-eindpunt en een HTTP-eindpunt beschikbaar, naast een Exchange-eindpunt voor metagegevens. Het TCP-eindpunt en het HTTP-eindpunt gebruiken de volgende bindingen, waarvoor beide de eigenschap <transactionFlow> zijn ingeschakeld.
<bindings>
<netTcpBinding>
<binding name="transactionalOleTransactionsTcpBinding"
transactionFlow="true"
transactionProtocol="OleTransactions"/>
</netTcpBinding>
<wsHttpBinding>
<binding name="transactionalWsatHttpBinding"
transactionFlow="true" />
</wsHttpBinding>
</bindings>
Notitie
De door het systeem geleverde netTcpBinding maakt specificatie van het transactionProtocol mogelijk, terwijl de door het systeem geleverde wsHttpBinding alleen het meer interoperabele WSAtomicTransactionOctober2004-protocol gebruikt. Het OleTransactions-protocol is alleen beschikbaar voor gebruik door WCF-clients (Windows Communication Foundation).
Voor de klasse die de ICalculator
-interface implementeert, zijn alle methoden voorzien van de TransactionScopeRequired-eigenschap ingesteld op true
. Met deze instelling wordt aangegeven dat alle acties die binnen de methode worden uitgevoerd, plaatsvinden binnen het bereik van een transactie. In dit geval omvatten de acties die worden uitgevoerd opname in de logboekdatabase. Als de bewerkingsaanvraag een gestroomde transactie bevat, worden de acties binnen het bereik van de binnenkomende transactie of een nieuw transactiebereik automatisch gegenereerd.
Notitie
De eigenschap TransactionScopeRequired definieert gedrag dat lokaal is voor de implementaties van de servicemethode en bepaalt niet of de client in staat is om een transactie te laten verlopen of daartoe verplicht is.
// 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
}
Op de client worden de TransactionFlowOption
instellingen van de service voor de bewerkingen weergegeven in de gegenereerde definitie van de ICalculator
-interface van de client. Bovendien worden de transactionFlow
eigenschapsinstellingen van de service weergegeven in de toepassingsconfiguratie van de client. De client kan het transport en protocol selecteren door de juiste endpointConfigurationName
te selecteren.
// Create a client using either wsat or oletx endpoint configurations
CalculatorClient client = new CalculatorClient("WSAtomicTransaction_endpoint");
// CalculatorClient client = new CalculatorClient("OleTransactions_endpoint");
Notitie
Het waargenomen gedrag van dit voorbeeld is hetzelfde, ongeacht welk protocol of transport wordt gekozen.
Nadat de verbinding met de service tot stand is gebracht, creëert de client een nieuwe TransactionScope
rond de aanroepen naar de service-activiteiten.
// 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");
De aanroepen naar de bewerkingen zijn als volgt:
De
Add
-aanvraag verzendt de benodigde transactie naar de service en de acties van de service vinden plaats binnen de context van de transactie van de klant.De eerste
Subtract
-aanvraag brengt ook de toegestane transactie naar de service en opnieuw vinden de acties van de service plaats binnen het bereik van de transactie van de cliënt.De tweede
Subtract
aanvraag wordt uitgevoerd binnen een nieuw transactiebereik dat is gedeclareerd met de optieTransactionScopeOption.Suppress
. Dit onderdrukt de eerste buitenste transactie van de client en de aanvraag leidt geen transactie door naar de service. Met deze benadering kan een client zich expliciet afmelden en beschermen tegen het stromen van een transactie naar een service wanneer dat niet vereist is. De acties van de service vinden plaats binnen het bereik van een nieuwe en niet-verbonden transactie.De
Multiply
-aanvraag leidt geen transactie naar de service omdat de door de client gegenereerde definitie van deICalculator
-interface een TransactionFlowAttribute bevat die is ingesteld op TransactionFlowOptionNotAllowed
.De
Divide
-aanvraag draagt geen transactie over naar de service, omdat de door de client gegenereerde definitie van deICalculator
-interface geenTransactionFlowAttribute
bevat. De acties van de service worden opnieuw uitgevoerd binnen het bereik van een andere nieuwe en niet-verbonden transactie.
Wanneer u het voorbeeld uitvoert, worden de bewerkingsaanvragen en -antwoorden weergegeven in het clientconsolevenster. Druk op Enter in het clientvenster om de client af te sluiten.
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.
De logboekregistratie van de servicebewerkingsaanvragen wordt weergegeven in het consolevenster van de service. Druk op Enter in het clientvenster om de client af te sluiten.
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
Na een geslaagde uitvoering wordt het transactiebereik van de client voltooid en worden alle acties die binnen dat bereik worden uitgevoerd, doorgevoerd. De genoteerde vijf records worden in de database van de service bewaard. De eerste twee hiervan zijn opgetreden binnen het kader van de transactie van de cliënt.
Als er ergens in de TransactionScope
van de client een uitzondering is opgetreden, kan de transactie niet worden voltooid. Dit zorgt ervoor dat de records die binnen dat bereik zijn vastgelegd, niet worden doorgevoerd in de database. Dit effect kan worden waargenomen door de voorbeelduitvoering te herhalen na het uitcommentariëren van de aanroep om de buitenste TransactionScope
te voltooien. Bij een dergelijke uitvoering worden alleen de laatste drie acties (vanaf de tweede Subtract
, de Multiply
en de Divide
-aanvragen) geregistreerd omdat de clienttransactie niet naar die acties is gestroomd.
Het voorbeeld instellen, compileren en uitvoeren
Als u de C#- of Visual Basic .NET-versie van de oplossing wilt bouwen, volgt u de instructies in De Windows Communication Foundation-voorbeelden bouwen.
Zorg ervoor dat u SQL Server Express Edition of SQL Server hebt geïnstalleerd en dat de verbindingsreeks correct is ingesteld in het toepassingsconfiguratiebestand van de service. Als u het voorbeeld wilt uitvoeren zonder een database te gebruiken, stelt u de
usingSql
waarde in het toepassingsconfiguratiebestand van de service in opfalse
.Als u het voorbeeld wilt uitvoeren in een configuratie met één of meerdere computers, volgt u de instructies in Windows Communication Foundation-voorbeelden uitvoeren.
Notitie
Voor configuratie tussen computers schakelt u de gedistribueerde transactiecoördinator in met behulp van de onderstaande instructies en gebruikt u het hulpprogramma WsatConfig.exe van de Windows SDK om WCF Transactions-netwerkondersteuning in te schakelen. Zie Configureren van WS-Atomic transactieondersteuningvoor meer informatie over het instellen van WsatConfig.exe.
Ongeacht of u het voorbeeld uitvoert op dezelfde computer of op verschillende computers, moet u de Microsoft Distributed Transaction Coordinator (MSDTC) configureren om netwerktransactiestroom in te schakelen en het hulpprogramma WsatConfig.exe te gebruiken om netwerkondersteuning voor WCF-transacties in te schakelen.
De Microsoft Distributed Transaction Coordinator (MSDTC) configureren ter ondersteuning van het uitvoeren van het voorbeeld
Configureer MSDTC op een servicecomputer met Windows Server 2003 of Windows XP om binnenkomende netwerktransacties toe te staan door deze instructies te volgen.
Ga in het menu Start naar Configuratiescherm, Systeembeheeren Component Services.
Vouw Component Servicesuit. Open de map Computers.
Klik met de rechtermuisknop op Mijn Computer en selecteer Eigenschappen.
Klik op het tabblad MSDTC op Beveiligingsconfiguratie.
Controleer DTC-netwerktoegang en het toestaan van binnenkomende .
Klik op OK-en klik vervolgens op Ja om de MSDTC-service opnieuw te starten.
Klik op OK- om het dialoogvenster te sluiten.
Configureer MSDTC op een servicecomputer met Windows Server 2008 of Windows Vista om binnenkomende netwerktransacties toe te staan door deze instructies te volgen.
Ga in het menu Start naar Configuratiescherm, Systeembeheeren Component Services.
Vouw Component Services-uit. Open de map Computers. Selecteer gedistribueerde transactiecoördinator.
Klik met de rechtermuisknop op DTC-Coördinator en selecteer Eigenschappen.
Controleer op het tabblad Security de opties Network DTC Access en InkomendeToestaan.
Klik op OK-en klik vervolgens op Ja om de MSDTC-service opnieuw te starten.
Klik op OK- om het dialoogvenster te sluiten.
Configureer MSDTC op de clientcomputer om uitgaande netwerktransacties toe te staan:
Ga in het menu Start naar
Control Panel
, Systeembeheeren Component Services.Klik met de rechtermuisknop op Mijn computer en selecteer eigenschappen.
Klik op het tabblad MSDTC op Beveiligingsconfiguratie.
Controleer Netwerk-DTC-toegang en Uitgaandetoestaan.
Klik op OK-en klik vervolgens op Ja om de MSDTC-service opnieuw te starten.
Klik op OK- om het dialoogvenster te sluiten.