Service Transaction Behavior
Cet exemple illustre l'utilisation d'une transaction coordonnée par le client et les paramètres de ServiceBehaviorAttribute et OperationBehaviorAttribute pour contrôler le comportement de la transaction du service. Cet exemple est basé sur l'Getting Started, exemple qui implémente un service de calculatrice, mais est étendu pour maintenir un journal de serveur des opérations effectuées dans une table de la base de données et un total évolutif avec état pour les opérations de calculatrice. Les écritures rendues persistantes dans la table du journal de serveur dépendent du résultat d'une transaction coordonnée par le client : si la transaction cliente ne se complète pas, la transaction de service Web garantit que les mises à jour de la base de données ne sont pas validées.
Remarque : |
---|
La procédure d'installation ainsi que les instructions de génération relatives à cet exemple figurent en fin de rubrique. |
Le contrat pour le service définit que toutes les opérations requièrent qu'une transaction soit transmise avec les demandes :
[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);
}
Pour activer le flux de transaction entrant, le service est configuré avec la wsHttpBinding fournie par le système, avec l'attribut transactionFlow ayant la valeur true. Cette liaison utilise le protocole WSAtomicTransactionOctober2004 interopérable :
<bindings>
<wsHttpBinding>
<binding name="transactionalBinding" transactionFlow="true" />
</wsHttpBinding>
</bindings>
Après avoir initialisé à la fois une connexion au service et une transaction, le client accède à plusieurs opérations de service dans l'étendue de cette transaction, puis complète la transaction et ferme la connexion :
// 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();
Sur le service, il y a trois attributs qui affectent le comportement de la transaction de service, et qui procèdent comme suit :
- Sur le ServiceBehaviorAttribute :
- La propriété TransactionTimeout spécifie le délai dans lequel une nouvelle transaction doit s'exécuter. Dans cet exemple, elle a pour valeur 30 secondes.
- La propriété TransactionIsolationLevel spécifie le niveau d'isolation que le service prend en charge. Il doit correspondre au niveau d'isolation du client.
- La propriété ReleaseServiceInstanceOnTransactionComplete spécifie si l'instance de service sous-jacente est recyclée à la fin de l'exécution d'une transaction. Si elle a la valeur false, le service maintient la même instance de service à travers les demandes de l'opération. Cela est nécessaire pour maintenir le total évolutif. Si elle a la valeur true, une nouvelle instance est générée après chaque action complétée.
- La propriété TransactionAutoCompleteOnSessionClose spécifie si les transactions en attente sont exécutées lorsque la session se ferme. Si elle a la valeur false, les opérations individuelles doivent affecter à la propriété OperationBehaviorAttributeTransactionAutoComplete la valeur true ou requérir explicitement un appel à la méthode SetTransactionComplete pour exécuter des transactions. Cet exemple illustre les deux approches.
- Sur le ServiceContractAttribute :
- La propriété SessionMode spécifie si le service met en corrélation les demandes appropriées dans une session logique. Étant donné que ce service inclut des opérations où la propriété OperationBehaviorAttribute TransactionAutoComplete a la valeur false (multiplication et division), SessionMode.Required doit être spécifié. Par exemple, l'opération de multiplication n'exécute pas sa transaction et à la place compte sur un appel ultérieur à l'opération de division pour s'exécuter à l'aide de la méthode SetTransactionComplete ; le service doit être en mesure de déterminer que ces opérations se produisent dans la même session.
- Sur le OperationBehaviorAttribute :
- La propriété TransactionScopeRequired spécifie si les actions de l'opération doivent être exécutées dans une étendue de transaction. Elle a la valeur true pour toutes les opérations dans cet exemple et, vu que le client transmet sa transaction à toutes les opérations, les actions se produisent dans l'étendue de cette transaction cliente.
- La propriété TransactionAutoComplete spécifie si la transaction dans laquelle la méthode s'exécute est automatiquement effectuée si aucune exception non prise en charge n'est levée. Comme décrit précédemment, cette propriété a la valeur true pour les opérations d'addition et de soustraction mais false pour les opérations de multiplication et de division. Les opérations d'addition et de soustraction s'exécutent automatiquement, l'opération de division s'exécute à travers un appel explicite à la méthode SetTransactionComplete, et l'opération de multiplication ne s'exécute mais à la place compte sur un appel ultérieur obligatoire, à l'opération de division par exemple, pour s'exécuter.
L'implémentation du service doté d'attributs se déroule comme suit :
[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 ommitted for brevity
}
Lorsque vous exécutez l'exemple, les demandes et réponses d'opération s'affichent dans la fenêtre de console du client. Appuyez sur ENTER dans la fenêtre du client pour l'arrêter.
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.
Le journal des demandes faites à l'opération de service est visible dans la fenêtre de console du service. Appuyez sur ENTER dans la fenêtre du client pour l'arrêter.
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
Notez qu'en plus de conserver le total évolutif des calculs, le service signale la création d'instances (une instance pour cet exemple) et enregistre les demandes d'opération dans une base de données. Étant donné que toutes les demandes transmettent la transaction du client, tout échec d'exécution de cette transaction entraîne la restauration de toutes les opérations de la base de données. Cela peut être démontré de plusieurs manières :
- Supprimez l'appel du client à tx.Complete () et répétez la transaction : le client quitte l'étendue de la transaction sans l'exécuter.
- Supprimez l'appel à l'opération de division du service : cela empêche l'action initiée par l'opération de multiplication de s'effectuer. Par conséquent, la transaction du client échoue également.
- Levez une exception non gérée n'importe où dans l'étendue de transaction du client : cela empêche également le client d'exécuter sa transaction.
Le résultat est toujours le même : aucune des opérations exécutées dans cette étendue n'est validée et le nombre de lignes rendues persistantes dans la base de données n'est pas incrémenté.
Remarque : |
---|
Dans le cadre du processus de génération, le fichier de la base de données est copié dans le dossier bin. Vous devez examiner cette copie du fichier de la base de données pour observer les lignes rendues persistantes dans le journal plutôt que dans le fichier inclus dans le projet Visual Studio. |
Pour configurer, générer et exécuter l'exemple
Assurez-vous d'avoir installé SQL Server 2005 Express Edition ou SQL Server 2005. Dans le fichier App.config du service, la connectionString de la base de données peut être définie ou les interactions de la base de données peuvent être désactivées en affectant la valeur false à l'appSettings usingSql.
Pour générer l'édition C# ou Visual Basic .NET de la solution, suivez les instructions figurant à la section Génération des exemples Windows Communication Foundation.
Pour exécuter l'exemple dans une configuration à un ou plusieurs ordinateurs, suivez les instructions indiquées dans Exécution des exemples Windows Communication Foundation.
Si vous exécutez l'exemple sur plusieurs ordinateurs, vous devez configurer le Microsoft Distributed Transaction Coordinator (MSDTC) pour activer le flux de transaction réseau et utiliser l'outil WsatConfig.exe pour activer la gestion réseau des transactions Windows Communication Foundation (WCF).
Pour configurer le Microsoft Distributed Transaction Coordinator (MSDTC) de manière à prendre en charge l'exécution de l'exemple sur plusieurs ordinateurs
Sur l'ordinateur de service, configurez MSDTC pour autoriser des transactions réseau entrantes.
- Dans le menu Démarrer, naviguez jusqu'au Panneau de configuration, puis allez dans Outils d'administration et Services de composants.
- Cliquez avec le bouton droit sur Poste de travail, puis sélectionnez Propriétés.
- Sous l'onglet MSDTC, cliquez sur Configuration de la sécurité.
- Cochez Accès DTC réseau et Autoriser les transactions entrantes.
- Cliquez Oui pour redémarrer le service MS DTC, puis cliquez sur OK.
- Cliquez sur OK pour fermer la boîte de dialogue.
Sur l'ordinateur du service et l'ordinateur du client, configurez le Pare-feu Windows pour inclure le Microsoft Distributed Transaction Coordinator (MSDTC) à la liste des exceptions :
- Exécutez l'application de Pare-feu Windows à partir du Panneau de configuration.
- Cliquez sur Ajouter un programme sous l'onglet Exceptions.
- Naviguez jusqu'au dossier C:\WINDOWS\System32.
- Sélectionnez Msdtc.exe et cliquez sur Ouvrir.
- Cliquez sur OK pour fermer la boîte de dialogue Ajouter un programme et cliquez à nouveau sur OK pour fermer l'applet du Pare-feu Windows.
Sur l'ordinateur du client, configurez MSDTC pour autoriser les transactions réseau sortantes :
- Dans le menu Démarrer, naviguez jusqu'au Panneau de configuration, puis allez dans Outils d'administration et Services de composants.
- Cliquez avec le bouton droit sur Poste de travail, puis sélectionnez Propriétés.
- Sous l'onglet MSDTC, cliquez sur Configuration de la sécurité.
- Cochez Accès DTC réseau et Autoriser les transactions sortantes.
- Cliquez Oui pour redémarrer le service MS DTC, puis cliquez sur OK.
- Cliquez sur OK pour fermer la boîte de dialogue.
Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.