Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El ejemplo TransactionFlow demuestra el uso de una transacción coordinada por el cliente, así como las opciones del cliente y del servidor para el flujo de transacciones utilizando el protocolo WS-Atomic Transaction o el protocolo OleTransactions. Este ejemplo se basa en el Getting Started que implementa un servicio de calculadora, pero las operaciones se asignan para demostrar el uso de TransactionFlowAttribute con la enumeración TransactionFlowOption para determinar en qué grado está habilitado el flujo de transacciones. Dentro del ámbito de la transacción fluida, se escribe un registro de las operaciones solicitadas en una base de datos y se conserva hasta que se haya completado la transacción coordinada por el cliente, si la transacción del cliente no se completa, la transacción del servicio web garantiza que no se confirmen las actualizaciones adecuadas de la base de datos.
Nota:
El procedimiento de instalación y las instrucciones de compilación de este ejemplo se encuentran al final de este tema.
Después de iniciar una conexión con el servicio y una transacción, el cliente accede a varias operaciones de servicio. El contrato para el servicio se define de la siguiente manera, con cada una de las operaciones mostrando una configuración diferente para el 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);
}
Esto define las operaciones en el orden en que se van a procesar:
Una solicitud de operación
Adddebe incluir una transacción fluida.Una solicitud de operación
Subtractpuede incluir una transacción fluida.Una solicitud de operación
Multiplyno debe incluir una transacción fluida a través del valor NotAllowed explícito.Una solicitud de operación
Divideno debe incluir una transacción fluida a través de la omisión de un atributoTransactionFlow.
Para habilitar el flujo de transacciones, se deben usar enlaces con la <propiedad transactionFlow> habilitada además de los atributos de operación adecuados. En este ejemplo, la configuración del servicio expone un punto de conexión TCP y un punto de conexión HTTP además de un punto de conexión de Intercambio de metadatos. El punto de conexión TCP y el punto de conexión HTTP usan las siguientes vinculaciones, ambos tienen habilitada la <propiedad transactionFlow> .
<bindings>
<netTcpBinding>
<binding name="transactionalOleTransactionsTcpBinding"
transactionFlow="true"
transactionProtocol="OleTransactions"/>
</netTcpBinding>
<wsHttpBinding>
<binding name="transactionalWsatHttpBinding"
transactionFlow="true" />
</wsHttpBinding>
</bindings>
Nota:
NetTcpBinding proporcionado por el sistema permite la especificación del protocolo transactionProtocol, mientras que wsHttpBinding proporcionado por el sistema solo usa el protocolo WSAtomicTransactionOctober2004 más interoperable. El protocolo OleTransactions solo está disponible para su uso por parte de los clientes de Windows Communication Foundation (WCF).
Para la clase que implementa la interfaz ICalculator, todos los métodos se atribuyen con la propiedad TransactionScopeRequired establecida en true. Esta configuración declara que todas las acciones realizadas en el método se producen dentro del ámbito de una transacción. En este caso, las acciones realizadas incluyen la grabación en la base de datos de registro. Si la solicitud de operación incluye una transacción fluyeda, las acciones se producen dentro del ámbito de la transacción entrante o se genera automáticamente un nuevo ámbito de transacción.
Nota:
La TransactionScopeRequired propiedad define el comportamiento local para las implementaciones del método de servicio y no define la capacidad o requisito del cliente para fluir una transacción.
// 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
}
En el cliente, la configuración del TransactionFlowOption servicio en las operaciones se refleja en la definición generada por el cliente de la ICalculator interfaz. Además, la configuración de las propiedades del servicio transactionFlow se refleja en la configuración de la aplicación del cliente. El cliente puede seleccionar el transporte y el protocolo seleccionando el adecuado endpointConfigurationName.
// Create a client using either wsat or oletx endpoint configurations
CalculatorClient client = new CalculatorClient("WSAtomicTransaction_endpoint");
// CalculatorClient client = new CalculatorClient("OleTransactions_endpoint");
Nota:
El comportamiento observado de este ejemplo es el mismo independientemente del protocolo o transporte que se elija.
Habiendo iniciado la conexión al servicio, el cliente crea un nuevo TransactionScope alrededor de las llamadas a las operaciones del servicio.
// 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");
Las llamadas a las operaciones son como sigue:
La
Addsolicitud transmite la transacción necesaria al servicio y las acciones del servicio se producen dentro del alcance de la transacción del cliente.La primera
Subtractsolicitud también transfiere la transacción permitida al servicio y, de nuevo, las acciones del servicio se producen dentro del ámbito de la transacción del cliente.La segunda
Subtractsolicitud se realiza dentro de un nuevo ámbito de transacción declarado con laTransactionScopeOption.Suppressopción . Esto suprime la transacción externa inicial del cliente y la solicitud no transmite ninguna transacción al servicio. Este enfoque permite que un cliente opte explícitamente por no participar y protegerse contra el flujo de una transacción a un servicio cuando no sea necesario. Las acciones del servicio se producen dentro del ámbito de una transacción nueva y no conectada.La
Multiplysolicitud no transfiere una transacción al servicio porque la definición generada por el cliente de la interfazICalculatorincluye un TransactionFlowAttribute establecido en TransactionFlowOptionNotAllowed.La solicitud
Divideno transfiere una transacción al servicio porque nuevamente la definición generada por el cliente de la interfazICalculatorno incluye unTransactionFlowAttribute. Las acciones del servicio se producen de nuevo dentro del ámbito de otra transacción nueva y no conectada.
Al ejecutar el ejemplo, las solicitudes de operación y las respuestas se muestran en la ventana de la consola del cliente. Presione ENTRAR en la ventana del cliente para apagar el cliente.
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.
El registro de solicitudes de operaciones del servicio se muestra en la ventana de consola del servicio. Presione ENTRAR en la ventana del cliente para apagar el cliente.
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
Después de una ejecución correcta, el ámbito de transacción del cliente se completa y se confirman todas las acciones realizadas dentro de ese ámbito. En concreto, los 5 registros indicados se conservan en la base de datos del servicio. Los primeros 2 de estos se han producido dentro del ámbito de la transacción del cliente.
Si se produjo una excepción en cualquier parte del cliente TransactionScope , la transacción no se puede completar. Esto hace que los registros registrados dentro de ese ámbito no se confirmen en la base de datos. Este efecto se puede observar repitiendo el ejemplo ejecutado después de marcar como comentario la llamada para completar el TransactionScope exterior. En este tipo de procesos, solo se registran las tres últimas acciones (desde la segunda solicitud Subtract, Multiply y Divide) porque la transacción del cliente no fluyó hacia ellas.
Para configurar, compilar y ejecutar el ejemplo
Para compilar la versión de .NET de C# o Visual Basic de la solución, siga las instrucciones de Creación de ejemplos de Windows Communication Foundation.
Asegúrese de que ha instalado SQL Server Express Edition o SQL Server y de que la cadena de conexión se ha establecido correctamente en el archivo de configuración de la aplicación del servicio. Para ejecutar el ejemplo sin usar una base de datos, establezca el valor de
usingSqlen el archivo de configuración de la aplicación del servicio enfalse.Para ejecutar el ejemplo en una configuración de una máquina única o entre máquinas, siga las instrucciones de Ejecución de los ejemplos de Windows Communication Foundation.
Nota:
Para la configuración entre máquinas, habilite el Coordinador de transacciones distribuidas con las instrucciones siguientes y use la herramienta WsatConfig.exe de Windows SDK para habilitar la compatibilidad con la red transacciones de WCF. Para obtener información sobre cómo configurar WsatConfig.exe, consulte Configuración de la compatibilidad con WS-Atomic Transaction.
Tanto si ejecuta el ejemplo en el mismo equipo como en equipos diferentes, debe configurar el Coordinador de transacciones distribuidas de Microsoft (MSDTC) para habilitar el flujo de transacciones de red y usar la herramienta WsatConfig.exe para habilitar la compatibilidad con la red de transacciones WCF.
Para configurar el Coordinador de transacciones distribuidas de Microsoft (MSDTC) para admitir la ejecución del ejemplo
En una máquina de servicio que ejecuta Windows Server 2003 o Windows XP, configure MSDTC para permitir transacciones de red entrantes siguiendo estas instrucciones.
En el menú Inicio , vaya al Panel de control, después Herramientas administrativas y, después, Servicios de componentes.
Expanda Component Services. Abra la carpeta Equipos .
Haga clic con el botón derecho en Mi PC y seleccione Propiedades.
En la pestaña MSDTC , haga clic en Configuración de seguridad.
Active las opciones Acceso a DTC desde la red y Permitir entrantes.
Haga clic en Aceptar y, a continuación, haga clic en Sí para reiniciar el servicio MSDTC.
Haga clic en Aceptar para cerrar el cuadro de diálogo.
En una máquina de servicio que ejecuta Windows Server 2008 o Windows Vista, configure MSDTC para permitir transacciones de red entrantes siguiendo estas instrucciones.
En el menú Inicio , vaya al Panel de control, después Herramientas administrativas y, después, Servicios de componentes.
Expanda Component Services. Abra la carpeta Equipos . Seleccione Coordinador de transacciones distribuidas.
Haga clic con el botón derecho en Coordinador de DTC y seleccione Propiedades.
En la pestaña Seguridad, active Acceso a DTC desde la red y Permitir entrantes.
Haga clic en Aceptar y, a continuación, haga clic en Sí para reiniciar el servicio MSDTC.
Haga clic en Aceptar para cerrar el cuadro de diálogo.
En el equipo cliente, configure MSDTC para permitir transacciones de red salientes:
En el menú Inicio , vaya a
Control Panel, después Herramientas administrativas y, a continuación, Servicios de componentes.Haga clic con el botón derecho en Mi PC y seleccione Propiedades.
En la pestaña MSDTC , haga clic en Configuración de seguridad.
Active las opciones Acceso a DTC desde la red y Permitir salientes.
Haga clic en Aceptar y, a continuación, haga clic en Sí para reiniciar el servicio MSDTC.
Haga clic en Aceptar para cerrar el cuadro de diálogo.