Services and Transactions
Windows Communication Foundation (WCF) applications can initiate a transaction from within a client and coordinate the transaction within the service operation. Clients can initiate a transaction and invoke several service operations and ensure that the service operations are either committed or rolled back as a single unit.
You can enable the transaction behavior in the service contract by specifying a ServiceBehaviorAttribute and setting its TransactionIsolationLevel and TransactionScopeRequired properties for service operations that require client transactions. The TransactionAutoComplete parameter specifies whether the transaction in which the method executes is automatically completed if no unhandled exceptions are thrown. For more information about these attributes, see ServiceModel Transaction Attributes.
The work that is performed in the service operations and managed by a resource manager, such as logging database updates, is part of the client’s transaction.
The following sample demonstrates usage of the ServiceBehaviorAttribute and OperationBehaviorAttribute attributes to control service-side transaction behavior.
[ServiceBehavior(TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable)]
public class CalculatorService: ICalculatorLog
{
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
public double Add(double n1, double n2)
{
recordToLog($"Added {n1} to {n2}");
return n1 + n2;
}
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
public double Subtract(double n1, double n2)
{
recordToLog($"Subtracted {n1} from {n2}");
return n1 - n2;
}
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
public double Multiply(double n1, double n2)
{
recordToLog($"Multiplied {n1} by {n2}");
return n1 * n2;
}
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
public double Divide(double n1, double n2)
{
recordToLog($"Divided {n1} by {n2}", n1, n2);
return n1 / n2;
}
}
You can enable transactions and transaction flow by configuring the client and service bindings to use the WS-AtomicTransaction protocol, and setting the <transactionFlow> element to true
, as shown in the following sample configuration.
<client>
<endpoint address="net.tcp://localhost/ServiceModelSamples/service"
binding="netTcpBinding"
bindingConfiguration="netTcpBindingWSAT"
contract="Microsoft.ServiceModel.Samples.ICalculatorLog" />
</client>
<bindings>
<netTcpBinding>
<binding name="netTcpBindingWSAT"
transactionFlow="true"
transactionProtocol="WSAtomicTransactionOctober2004" />
</netTcpBinding>
</bindings>
Clients can begin a transaction by creating a TransactionScope and invoking service operations within the scope of the transaction.
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew))
{
//Do work here
ts.Complete();
}