Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Exemplet Transaktioner visar användningen av en klientkoordinerad transaktion och inställningarna för ServiceBehaviorAttribute och OperationBehaviorAttribute för att kontrollera tjänstens transaktionsbeteende. Det här exemplet baseras på det Komma igång exempel som implementerar en kalkylatortjänst, men utökas för att underhålla en serverlogg för de utförda åtgärderna i en databastabell och en tillståndskänslig totalkörning för kalkylatoråtgärderna. Beständiga skrivningar till serverloggtabellen är beroende av resultatet av en klientkoordinerad transaktion – om klienttransaktionen inte slutförs säkerställer webbtjänsttransaktionen att uppdateringarna till databasen inte checkas in.
Kommentar
Installationsproceduren och bygginstruktionerna för det här exemplet finns i slutet av den här artikeln.
Kontraktet för tjänsten definierar att alla åtgärder kräver att en transaktion flödas med begäranden:
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples",
SessionMode = SessionMode.Required)]
public interface ICalculator
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
double Add(double n);
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
double Subtract(double n);
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
double Multiply(double n);
[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
double Divide(double n);
}
För att aktivera inkommande transaktionsflöde konfigureras tjänsten med det systembaserade wsHttpBinding med attributet transactionFlow inställt på true. Den här bindningen använder det samverkande protokollet WSAtomicTransactionOctober2004:
<bindings>
<wsHttpBinding>
<binding name="transactionalBinding" transactionFlow="true" />
</wsHttpBinding>
</bindings>
När du har initierat både en anslutning till tjänsten och en transaktion kommer klienten åt flera tjänståtgärder inom transaktionens omfång och slutför sedan transaktionen och stänger anslutningen:
// Create a client
CalculatorClient client = new CalculatorClient();
// Create a transaction scope with the default isolation level of Serializable
using (TransactionScope tx = new TransactionScope())
{
Console.WriteLine("Starting transaction");
// Call the Add service operation.
double value = 100.00D;
Console.WriteLine(" Adding {0}, running total={1}",
value, client.Add(value));
// Call the Subtract service operation.
value = 45.00D;
Console.WriteLine(" Subtracting {0}, running total={1}",
value, client.Subtract(value));
// Call the Multiply service operation.
value = 9.00D;
Console.WriteLine(" Multiplying by {0}, running total={1}",
value, client.Multiply(value));
// Call the Divide service operation.
value = 15.00D;
Console.WriteLine(" Dividing by {0}, running total={1}",
value, client.Divide(value));
Console.WriteLine(" Completing transaction");
tx.Complete();
}
Console.WriteLine("Transaction committed");
// Closing the client gracefully closes the connection and cleans up resources
client.Close();
I tjänsten finns det tre attribut som påverkar beteendet för tjänsttransaktionen, och de gör det på följande sätt:
På :
ServiceBehaviorAttributeEgenskapen
TransactionTimeoutanger den tidsperiod inom vilken en transaktion måste slutföras. I det här exemplet är det inställt på 30 sekunder.Egenskapen
TransactionIsolationLevelanger den isoleringsnivå som tjänsten stöder. Detta krävs för att matcha klientens isoleringsnivå.Egenskapen
ReleaseServiceInstanceOnTransactionCompleteanger om tjänstinstansen återvinns när en transaktion slutförs. Genom att ställa in den påfalseunderhåller tjänsten samma tjänstinstans över åtgärdsbegäranden. Detta krävs för att behålla den löpande summan. Om den är inställdtruepå genereras en ny instans efter varje slutförd åtgärd.Egenskapen
TransactionAutoCompleteOnSessionCloseanger om utestående transaktioner slutförs när sessionen stängs. Genom att ange den tillfalsemåste de enskilda åtgärderna antingen ange OperationBehaviorAttribute.TransactionAutoComplete egenskapen tilltrueeller uttryckligen kräva ett anrop till OperationContext.SetTransactionComplete() metoden för att slutföra transaktioner. Det här exemplet visar båda metoderna.
På :
ServiceContractAttribute- Egenskapen
SessionModeanger om tjänsten korrelerar lämpliga begäranden till en logisk session. Eftersom den här tjänsten innehåller åtgärder där egenskapen OperationBehaviorAttribute TransactionAutoComplete är inställd påfalse(Multiplicera och dividera)SessionMode.Requiredmåste anges. Åtgärden Multiplicera slutför till exempel inte transaktionen och förlitar sig i stället på ett senare anrop för att dividera för att slutföra med hjälp avSetTransactionCompletemetoden. Tjänsten måste kunna fastställa att dessa åtgärder utförs inom samma session.
- Egenskapen
På :
OperationBehaviorAttributeEgenskapen
TransactionScopeRequiredanger om åtgärdens åtgärder ska utföras inom ett transaktionsomfång. Detta är inställt påtrueför alla åtgärder i det här exemplet och eftersom klienten flödar sin transaktion till alla åtgärder sker åtgärderna inom omfånget för den klienttransaktionen.Egenskapen
TransactionAutoCompleteanger om transaktionen där metoden körs slutförs automatiskt om inga ohanterade undantag inträffar. Som tidigare beskrivits är detta inställt påtrueför åtgärderna Lägg till och Subtrahera, menfalseför åtgärderna Multiplicera och Dela. Åtgärderna Lägg till och subtrahera slutför sina åtgärder automatiskt, Dividera slutför sina åtgärder via ett explicit anrop tillSetTransactionCompletemetoden och Multiplicera slutför inte sina åtgärder utan förlitar sig i stället på och kräver ett senare anrop, till exempel dividera, för att slutföra åtgärderna.
Implementeringen av den tilldelade tjänsten är följande:
[ServiceBehavior(
TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable,
TransactionTimeout = "00:00:30",
ReleaseServiceInstanceOnTransactionComplete = false,
TransactionAutoCompleteOnSessionClose = false)]
public class CalculatorService : ICalculator
{
double runningTotal;
public CalculatorService()
{
Console.WriteLine("Creating new service instance...");
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public double Add(double n)
{
RecordToLog(String.Format(CultureInfo.CurrentCulture, "Adding {0} to {1}", n, runningTotal));
runningTotal = runningTotal + n;
return runningTotal;
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public double Subtract(double n)
{
RecordToLog(String.Format(CultureInfo.CurrentCulture, "Subtracting {0} from {1}", n, runningTotal));
runningTotal = runningTotal - n;
return runningTotal;
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
public double Multiply(double n)
{
RecordToLog(String.Format(CultureInfo.CurrentCulture, "Multiplying {0} by {1}", runningTotal, n));
runningTotal = runningTotal * n;
return runningTotal;
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
public double Divide(double n)
{
RecordToLog(String.Format(CultureInfo.CurrentCulture, "Dividing {0} by {1}", runningTotal, n));
runningTotal = runningTotal / n;
OperationContext.Current.SetTransactionComplete();
return runningTotal;
}
// Logging method omitted for brevity
}
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
Performing calculations...
Adding 100, running total=100
Subtracting 45, running total=55
Multiplying by 9, running total=495
Dividing by 15, running total=33
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 service.
Creating new service instance...
Writing row 1 to database: Adding 100 to 0
Writing row 2 to database: Subtracting 45 from 100
Writing row 3 to database: Multiplying 55 by 9
Writing row 4 to database: Dividing 495 by 15
Observera att förutom att behålla den löpande summan av beräkningarna rapporterar tjänsten skapandet av instanser (en instans för det här exemplet) och loggar åtgärdsbegäranden till en databas. Eftersom alla begäranden flödar klientens transaktion resulterar eventuella misslyckade transaktioner i alla databasåtgärder som återställs. Detta kan demonstreras på flera olika sätt:
Kommentera ut klientens anrop till
tx.Complete() och kör igen – detta resulterar i att klienten avslutar transaktionsomfånget utan att slutföra transaktionen.Kommentera ut anropet till åtgärden Dividera tjänst – det här resultatet hindrar åtgärden som initierades av åtgärden Multiplicera från att slutföras och därmed misslyckas även klientens transaktion.
Generera ett ohanterat undantag var som helst i klientens transaktionsomfång – detta förhindrar på samma sätt klienten från att slutföra sin transaktion.
Resultatet av något av dessa är att ingen av de åtgärder som utförs inom det omfånget har checkats in och antalet rader som sparats i databasen inte ökar.
Kommentar
Som en del av byggprocessen kopieras databasfilen till mappen bin. Du måste titta på den kopian av databasfilen för att se de rader som sparas i loggen i stället för filen som ingår i Visual Studio-projektet.
Så här konfigurerar du, skapar och kör exemplet
Kontrollera att du har installerat SQL Server 2005 Express Edition eller SQL Server 2005. I tjänstens App.config-fil kan databasen
connectionStringanges eller så kan databasinteraktionerna inaktiveras genom att värdet appSettingsusingSqlanges tillfalse.Om du vill skapa C# eller Visual Basic .NET-versionen av lösningen följer du anvisningarna i Skapa Windows Communication Foundation-exempel.
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.
Om du kör exemplet mellan 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 (Windows Communication Foundation).
Så här konfigurerar du Microsoft Distributed Transaction Coordinator (MSDTC) för att stödja körning av exemplet mellan datorer
På tjänstdatorn konfigurerar du MSDTC så att inkommande nätverkstransaktioner tillåts.
Från Start-menyn går du till Kontrollpanelen, 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 inkommande trafik.
Klicka på Ja för att starta om MS DTC-tjänsten och klicka sedan på OK.
Stäng dialogrutan genom att klicka på OK.
På tjänstdatorn och klientdatorn konfigurerar du Windows-brandväggen så att den inkluderar Microsoft Distributed Transaction Coordinator (MSDTC) i listan över undantagna program:
Kör Windows-brandväggsprogrammet från Kontrollpanelen.
På fliken Undantag klickar du på Lägg till program.
Bläddra till mappen C:\WINDOWS\System32.
Välj Msdtc.exe och klicka på Öppna.
Klicka på OK för att stänga dialogrutan Lägg till program och klicka på OK igen för att stänga Applet för Windows-brandväggen.
På klientdatorn konfigurerar du MSDTC så att utgående nätverkstransaktioner tillåts:
Från Start-menyn går du till Kontrollpanelen, 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å Ja för att starta om MS DTC-tjänsten och klicka sedan på OK.
Stäng dialogrutan genom att klicka på OK.