http://msdn.microsoft.com/en-us/library/ff384250.aspx
To add transaction support to a WCF service, you will take the following actions:Server:
- transaction support to the service contract. This is required.
- Add transaction support to the code that implements the service contract. This is required.
- Configure transactions in the implementation code. This is optional.
- Enable transactions on the binding. This is required.
- Use the TransactionScope Class to Start a Transaction
<bindings> <wsHttpBinding> <binding name="wsHttpBinding" transactionFlow="true" /> </wsHttpBinding> </bindings> </system.serviceModel> Add the following code to apply this setting to the binding specified in the endpoint: <services> <service name="OrdersServiceLibrary.OrdersService" behaviorConfiguration="ServiceBehavior"> <!-- Service Endpoints --> <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding" contract="OrdersServiceLibrary.IOrdersService">
[OperationContract]
[TransactionFlow(TransactionFlowOption.NotAllowed)]
List<Customer> GetCustomers();
The TransactionFlow attribute specifies whether the operation supports transactions. There are three possible values for this attribute:
- NotAllowed : The operation cannot participate in a transaction. This is the default value for this attribute.
- Allowed : The operation will participate in a transaction if the client creates one.
- Mandatory : In order to call this operation, the client must create a transaction.
[OperationBehavior(TransactionScopeRequired=true,
TransactionAutoComplete=true)]
public string PlaceOrder(Order order)
When you added the TransactionFlow attribute to the service contract, you enabled clients to start a transaction. Here, you are instructing the WCF runtime to include these methods in transactions. Both steps are required to add transaction support to the service.
Setting the TransactionScopeRequired property to true specifies that clients cannot call these methods unless they are part of a transaction. Setting the TransactionAutoComplete property to true specifies that the transaction will complete automatically if no exceptions occur. This is the default value for this property.
3) Configure Transactions in the Implementation Code[ServiceBehavior(
TransactionIsolationLevel=
System.Transactions.IsolationLevel.Serializable,
TransactionTimeout="00:00:30")]
public class OrdersService : IOrdersService
The TransactionIsolationLevel property of the ServiceBehavior attribute specifies the locking behavior for the workflow. The isolation levels you will use most often are:
- Serializable. This is the default level of isolation used by the .NET Framework. It is also the most restrictive level. Other transactions cannot change any data read by this transaction until the transaction completes. The transaction can safely reread its data, knowing that other transactions have not changed it. This provides the most protection for the transaction, but can cause performance problems due to excessive locking of database records. This is a good choice for short transactions, but if your transactions are longer, you may want to use another level of isolation.
- RepeatableRead. Other transactions cannot update any data read by this transaction. However, they can insert rows. If the transaction needs to reread rows, there is a risk of additional data being present. This may cause unexpected results in some cases, but will improve performance.
- ReadCommitted. Other transactions can change data read by the transaction. However, they cannot read data changed by the transaction until it commits. This is the default isolation level in SQL Server.
- ReadUncommitted. Other transactions can change data read by the transaction. They can also read data changed by the transaction before it commits. This may cause the other transactions to read incomplete or inaccurate data.
- Unspecified. The service does not know ahead of time what level of isolation the transaction will use. This is the default value for the TransactionIsolationLevel property in a WCF service.
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding"
transactionFlow="true" />
</wsHttpBinding>
</bindings>
</system.serviceModel>
Add the following code to apply this setting to the binding specified in the endpoint:
<services>
<service name="OrdersServiceLibrary.OrdersService"
behaviorConfiguration="ServiceBehavior">
<!-- Service Endpoints -->
<endpoint address="" binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding"
contract="OrdersServiceLibrary.IOrdersService">
using (var tranScope = new TransactionScope())
{
try
{
...
tranScope.Complete();
}
// C#
[ServiceContract(SessionMode=SessionMode.Required)]
public interface IOrdersService
2.
change the instancing to PerSession and to complete the transaction when the session ends:
[ServiceBehavior(
TransactionIsolationLevel=
System.Transactions.IsolationLevel.Serializable,
TransactionTimeout="00:00:30",
InstanceContextMode=InstanceContextMode.PerSession,
TransactionAutoCompleteOnSessionClose=true)]
public class OrdersService : IOrdersService
[OperationBehavior(TransactionScopeRequired=true,
TransactionAutoComplete=false)]
public string PlaceOrder(Order order)
Client
using (var tranScope = new TransactionScope())
{
proxy = new OrdersServiceClient("WSHttpBinding_IOrdersService");
try
{
result = proxy.PlaceOrder(order);
MessageBox.Show(result);
result = proxy.AdjustInventory(product.ProductId, quantity);
MessageBox.Show(result);
result = proxy.AdjustBalance(customer.CustomerId,
Convert.ToDecimal(quantity) * order.Price);
MessageBox.Show(result);
proxy.Close();
tranScope.Complete();
}