WS-transaktionsflöde
TransactionFlow-exemplet visar användningen av en klientkoordinerad transaktion och klient- och serveralternativen för transaktionsflödet med antingen WS-Atomic Transaction eller OleTransactions-protokollet. Det här exemplet baseras på komma igång som implementerar en kalkylatortjänst, men åtgärderna tillskrivs för att demonstrera användningen av TransactionFlowAttribute
med TransactionFlowOption-uppräkningen för att avgöra i vilken grad transaktionsflödet är aktiverat. Inom omfånget för den flödesbaserade transaktionen skrivs en logg över de begärda åtgärderna till en databas och bevaras tills den klientkoordinerade transaktionen har slutförts – om klienttransaktionen inte slutförs säkerställer webbtjänsttransaktionen att lämpliga uppdateringar av databasen inte har checkats in.
Kommentar
Installationsproceduren och bygginstruktionerna för det här exemplet finns i slutet av det här avsnittet.
När du har initierat en anslutning till tjänsten och en transaktion kommer klienten åt flera tjänståtgärder. Kontraktet för tjänsten definieras enligt följande med var och en av åtgärderna som visar en annan inställning för 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);
}
Detta definierar åtgärderna i den ordning de ska bearbetas:
En
Add
åtgärdsbegäran måste innehålla en flödestransaktion.En
Subtract
åtgärdsbegäran kan innehålla en flödestransaktion.En
Multiply
åtgärdsbegäran får inte innehålla en flödestransaktion via den explicita inställningen NotAllowed.En
Divide
åtgärdsbegäran får inte innehålla en flödestransaktion genom utelämnande av ettTransactionFlow
attribut.
För att aktivera transaktionsflödet måste bindningar med <egenskapen transactionFlow> aktiveras användas utöver lämpliga åtgärdsattribut. I det här exemplet exponerar tjänstens konfiguration en TCP-slutpunkt och en HTTP-slutpunkt utöver en Metadata Exchange-slutpunkt. TCP-slutpunkten och HTTP-slutpunkten använder följande bindningar, som båda har <egenskapen transactionFlow> aktiverad.
<bindings>
<netTcpBinding>
<binding name="transactionalOleTransactionsTcpBinding"
transactionFlow="true"
transactionProtocol="OleTransactions"/>
</netTcpBinding>
<wsHttpBinding>
<binding name="transactionalWsatHttpBinding"
transactionFlow="true" />
</wsHttpBinding>
</bindings>
Kommentar
Det systembaserade netTcpBinding tillåter specifikation av transactionProtocol, medan det systembaserade wsHttpBinding endast använder det mer driftskompatibla WSAtomicTransactionOctober2004-protokollet. OleTransactions-protokollet är endast tillgängligt för användning av WCF-klienter (Windows Communication Foundation).
För klassen som implementerar gränssnittet tilldelas ICalculator
alla metoder med TransactionScopeRequired egenskapen inställd på true
. Den här inställningen deklarerar att alla åtgärder som vidtas inom metoden sker inom omfånget för en transaktion. I det här fallet inkluderar de åtgärder som vidtas inspelning till loggdatabasen. Om åtgärdsbegäran innehåller en flödestransaktion sker åtgärderna inom omfånget för den inkommande transaktionen eller så genereras automatiskt ett nytt transaktionsomfång.
Kommentar
Egenskapen TransactionScopeRequired definierar beteendet som är lokalt för tjänstmetodimplementeringarna och definierar inte klientens förmåga till eller krav för att flöda en transaktion.
// 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
}
På klienten återspeglas tjänstens TransactionFlowOption
inställningar för åtgärderna i klientens genererade definition av ICalculator
gränssnittet. Dessutom återspeglas tjänstens egenskapsinställningar transactionFlow
i klientens programkonfiguration. Klienten kan välja transport och protokoll genom att välja lämplig endpointConfigurationName
.
// Create a client using either wsat or oletx endpoint configurations
CalculatorClient client = new CalculatorClient("WSAtomicTransaction_endpoint");
// CalculatorClient client = new CalculatorClient("OleTransactions_endpoint");
Kommentar
Det observerade beteendet för det här exemplet är detsamma oavsett vilket protokoll eller vilken transport som väljs.
Efter att ha initierat anslutningen till tjänsten skapar klienten en ny TransactionScope
kring anropen till tjänståtgärderna.
// 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");
Anropen till åtgärderna är följande:
Begäran
Add
flödar den nödvändiga transaktionen till tjänsten och tjänstens åtgärder sker inom omfånget för klientens transaktion.Den första
Subtract
begäran flödar även den tillåtna transaktionen till tjänsten och återigen sker tjänstens åtgärder inom omfånget för klientens transaktion.Den andra
Subtract
begäran utförs inom ett nytt transaktionsomfång som deklareratsTransactionScopeOption.Suppress
med alternativet . Detta undertrycker klientens första yttre transaktion och begäran flödar inte en transaktion till tjänsten. Med den här metoden kan en klient uttryckligen välja bort och skydda mot att en transaktion flödar till en tjänst när det inte krävs. Tjänstens åtgärder sker inom ramen för en ny och oansluten transaktion.Begäran
Multiply
flödar inte en transaktion till tjänsten eftersom klientens genererade definition avICalculator
gränssnittet innehåller en TransactionFlowAttribute uppsättning till TransactionFlowOptionNotAllowed
.Begäran
Divide
flödar inte en transaktion till tjänsten eftersom klientens genererade definition avICalculator
gränssnittet inte innehåller någonTransactionFlowAttribute
. Tjänstens åtgärder sker igen inom ramen för en annan ny och oansluten transaktion.
När du kör exemplet visas åtgärdsbegäranden och svar i klientkonsolfönstret. Tryck på RETUR i klientfönstret för att stänga av klienten.
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.
Loggningen av tjänståtgärdsbegäranden visas i tjänstens konsolfönster. Tryck på RETUR i klientfönstret för att stänga av klienten.
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
Efter en lyckad körning slutförs klientens transaktionsomfång och alla åtgärder som vidtas inom det omfånget utförs. Mer specifikt sparas de antecknade 5 posterna i tjänstens databas. De första två av dessa har inträffat inom omfånget för klientens transaktion.
Om ett undantag inträffade någonstans inom klientens kan transaktionen inte slutföras TransactionScope
. Detta gör att de poster som loggas inom det omfånget inte checkas in i databasen. Den här effekten kan observeras genom att upprepa exempelkörningen när du har kommenterat ut anropet för att slutföra den yttre TransactionScope
. Vid en sådan körning loggas endast de tre sista åtgärderna (från den andra Subtract
, Multiply
och begärandena Divide
) eftersom klienttransaktionen inte flödade till dem.
Så här konfigurerar du, skapar och kör exemplet
Om du vill skapa C# eller Visual Basic .NET-versionen av lösningen följer du anvisningarna i Skapa Windows Communication Foundation-exempel
Kontrollera att du har installerat SQL Server Express Edition eller SQL Server och att anslutningssträng har angetts korrekt i tjänstens programkonfigurationsfil. Om du vill köra exemplet utan att använda en databas anger du
usingSql
värdet i tjänstens programkonfigurationsfil tillfalse
Om du vill köra exemplet i en konfiguration med en eller flera datorer följer du anvisningarna i Köra Windows Communication Foundation-exempel.
Kommentar
För konfiguration mellan datorer aktiverar du Distributed Transaction Coordinator med hjälp av anvisningarna nedan och använder verktyget WsatConfig.exe från Windows SDK för att aktivera nätverksstöd för WCF-transaktioner. Information om hur du konfigurerar WsatConfig.exe finns i Konfigurera WS-Atomic Transaction Support.
Oavsett om du kör exemplet på samma dator eller på olika datorer måste du konfigurera Microsoft Distributed Transaction Coordinator (MSDTC) för att aktivera nätverkstransaktionsflöde och använda verktyget WsatConfig.exe för att aktivera nätverksstöd för WCF-transaktioner.
Konfigurera Microsoft Distributed Transaction Coordinator (MSDTC) för att stödja körning av exemplet
På en tjänstdator som kör Windows Server 2003 eller Windows XP konfigurerar du MSDTC för att tillåta inkommande nätverkstransaktioner genom att följa dessa instruktioner.
Från Start-menyn går du till Kontrollpanelen, sedan Administrationsverktyg och sedan Komponenttjänster.
Expandera Komponenttjänster. Öppna mappen Datorer.
Högerklicka på Min dator och välj Egenskaper.
På fliken MSDTC klickar du på Säkerhetskonfiguration.
Kontrollera nätverks-DTC-åtkomst och Tillåt inkommande trafik.
Klicka på OK och klicka sedan på Ja för att starta om MSDTC-tjänsten.
Stäng dialogrutan genom att klicka på OK.
På en tjänstdator som kör Windows Server 2008 eller Windows Vista konfigurerar du MSDTC för att tillåta inkommande nätverkstransaktioner genom att följa dessa instruktioner.
Från Start-menyn går du till Kontrollpanelen, sedan Administrationsverktyg och sedan Komponenttjänster.
Expandera Komponenttjänster. Öppna mappen Datorer. Välj Distribuerad transaktionskoordinator.
Högerklicka på DTC-koordinator och välj Egenskaper.
På fliken Säkerhet markerar du Nätverks-DTC-åtkomst och Tillåt inkommande trafik.
Klicka på OK och klicka sedan på Ja för att starta om MSDTC-tjänsten.
Stäng dialogrutan genom att klicka på OK.
På klientdatorn konfigurerar du MSDTC så att utgående nätverkstransaktioner tillåts:
Från Start-menyn går du till
Control Panel
, sedan Administrationsverktyg och sedan Komponenttjänster.Högerklicka på Min dator och välj Egenskaper.
På fliken MSDTC klickar du på Säkerhetskonfiguration.
Kontrollera Nätverks-DTC-åtkomst och Tillåt utgående trafik.
Klicka på OK och klicka sedan på Ja för att starta om MSDTC-tjänsten.
Stäng dialogrutan genom att klicka på OK.