Part 1 of this chapter: wcf4.0 advanced series-Chapter 9 transaction support (Part 1)
[Body]
Design a transaction-supporting WCF Service
The content in the previous sections of this chapter shows you how to implement transactions in the WCF Service, but there are still many issues worth your attention when designing the WCF Service that supports transactions.
Transaction, session, and service instance mode
If you set the value of the transactionautocomplete attribute of the operationbehavior feature class to false on one or more operations in the WCF Service, you must set the service instance mode to persession. This is because the transaction status needs to be maintained between two call operations during the WCF operation. If the value of transactionautocomplete is set to true for each operation, the transaction State does not need to be maintained during the running of WCF because it completes the current transaction at the end of each operation, in this case, you can use the percall or single service instance mode.
When you use the persession service instance mode, the servicebehavior feature class provides two additional properties for WCF:
- Releaseserviceinstanceontransactioncomplete. If this attribute is set to true, the session is automatically ended and the service instance is recycled when each transaction ends. If the clientProgramCall another operation, which must be created and connected to a new service instance. Setting this attribute to false allows a session to process multiple transactions. The default value of this attribute is true.
- Transactionautocompleteonsessionclose. If this attribute is set to true, when the client program closes the session, the current transaction is automatically completed during the WCF operation. The default value of this attribute is false. When the client closes the session, the transaction is discarded and the work done by the transaction is restored.
From the above two points, you should remember the important point,Transactions cannot span multiple sessions.. In practice, this means that if a client initiates a transaction and sends a request to the service to execute some work and then closes the connection, the transaction will be terminated. The result of the transaction depends on whether the final operation has successfully completed the transaction, or call settransactioncomplete, or set the transactionautocomplete attribute to true on the called operation. If none of the above methods is used, the transaction will be discarded and the work executed in the transaction will be rolled back.
It seems to be a disadvantage, but it is actually very useful. If a transaction exists across multiple sessions, it cannot be guaranteed that a transaction has been terminated, in addition, the resources locked by a transaction may retain uncertain locks (other transactions may also lock the resource ).
Transactions and message transmission
Transaction operations return information about the transaction status to the client program. All defined messages so far follow the request/response model. The client sends the request and waits for the response from the service. In Chapter 12th "Implementing unidirectional and asynchronous operations", you can define unidirectional operations. This type of operation does not need to return a response to the client program. Please note that,One-way operations do not support transactions.
Transactions and Multithreading
As you can see in chapter 7, if the concurrencymode attribute is set to multiple, the WCF Service can implement multiple concurrent calls to operations. When using this mode, pay attention to the following points:
- Add the operationbehavior feature for each operation in the service, and the transactionautocomplete attribute of this feature class must be set to true. Transactions cannot span multiple operations.
- Add the servicebehavior feature to the service contract, and set the releaseserviceinstanceontransactioncomplete attribute of the feature class to false. When the client closes the connection, it must release the service instance explicitly.
- Add the servicebehavior feature to the service contract, and the transactionautocompleteonsessionclose attribute of the feature class must be set to true. When the session ends, transactions on all threads must be terminated.
Implement transactions in the workflow service
WF provides the transactedreceivescope activity in the message module transfer area on the toolbar to implement transactional operations in the workflow service. The activity discloses two attributes.
- Request. This attribute must be a receive activity, which defines the message received by the service and marks the start of the operation.
- Body, which contains an activity that defines the operation logic. Generally, you process client request data through ordered Activities to implement this activity. This activity also contains a sendreply activity to return a Response Message to the client.
Shows the transactedreceivescope activity, which implements the changestocklevel operation in the product service. This operation updates the number of products in the adventureworks database. TheCodeThis bookSource codeIn the productsworlflow solution under the chapter9 folder. Note that the request attribute contains a receive activity that listens to messages requesting changestocklevel operations. The body attribute contains a sequence activity, this activity calls the changestocklevel custom activity (in fact, this activity modifies the inventory quantity); the body property also contains a sendreply activity, which sends the updated result to the client (if the modification is successful, return true, otherwise, false is returned ).
Compared with the definition and control modes of the non-workflow WCF Service, the transactional activities in the workflow service are fundamentally different:
- You cannot explicitly specify how transactions are completed during Workflow running (for non-workflow services, there is no concept of the transactionautocomplete feature ). In the workflow service, the transactedreceivescope activity determines the operation result. If the transactedreceivescope defined by the sequence activity in the body property ends and no exception occurs, the operation is considered successful, and the commit process is entered when the transaction is completed. If an exception is thrown in the body attribute, the transaction will be discarded.
- Transactional work will not end in the sendreply activity. Sequence activities defined in the body property can include other logics after the response is sent. The work contained in these logics is also within the scope of the same transaction. Transactions can be identified only when the sequence activity ends. Note that this means that the workflow service may send a response to the client, execute other processes that may fail, and then discard the transaction. However, in this case, the client program may fail to know the transaction immediately, so be careful when using this feature.
- Using the transactedreceivd activity to implement an operation implies transactionflowoption. allowed. You cannot specify that an operation must be executed in an existing transaction (transactionflowoption. Mandatory). If a client program does not use a transaction to call the operation, a transaction is automatically created when the workflow is running. In addition, the default isolation level of the transaction is serializeable, although this will be overwritten by the isolation level in the transaction scope created by the client program.
You can use the transactionscope activity in the workflow client to start a transaction. The attribute provided by this activity allows you to specify the transaction isolation level and timeout. Shows a simple client workflow program that calls the changestocklevel operation.
This workflow creates a transactionscope activity, which contains an ordered activity, and then calls the changestocklevel operation twice in the ordered activity. Both operations are included in the same transaction. You can view transaction statistics in the component service console to confirm this. For additional checks, changestocklevel custom activities will output transaction details on the console. We can see that the transaction IDs of the two changestocklevel operations are the same.
Long-running transactions
The transaction locks the resource. To reduce the impact on other users and improve the high availability and concurrency of services, you should design transactions that run for as short as possible and avoid waiting for user input during transaction execution. Although the shopping cart service is used in this chapter to demonstrate transactions, its implementation is not the best practice (because the actual situation is significantly different from the exercises in this chapter ); if you use the GUI client created in the previous section to access the shoppingcartservice, the transaction may last for a long time (you cannot control when the user calls the checkout operation), during which time the resource is locked.
Another common scenario is the B2B solution. Transactions between enterprises can last for a long period of time (maybe several days), which is common. You need to use a replaceable solution for such a long-running transaction. A common solution is to execute an update for a service and immediately release the corresponding resources. This effectively treats every change as a separate transaction. The Service should maintain a changed list. In the future, if the service needs to roll back these operations, you can access the list and perform reverse operations. This recovery operation is sometimes called a compensatory transaction ". The compensableactivity activity provided by WF aims to achieve this goal.
The compensableactivity activity provides a body attribute in which you can define workflows for long-running tasks, such as waiting for client input or waiting for messages from other services. If an error occurs, you can define the compensation logic in the cancellationhandler attribute to restore the changes made by the workflow in the body attribute. If the workflow in the body property has been completed, you can still define the appropriate logical recovery changes in the cancellationhandler property. All changes are considered permanent only when the work executed by the compensableactivity activity is confirmed. To confirm the work performed by the compensableactivity activity, you need to use the confirm activity.
Creating compensatory transactions can cause many potential problems. For example, if another user has made further changes to the same data during the execution of the compensatory transaction, it may not be able to recover an operation. In addition, other users can see the data that the compensatory transaction has changed, because if you restore these operations, the transactions of other users may produce some inconsistencies.
More details, beyond the scope of this book, if you are interested, please refer to the msdn http://msdn.microsoft.com/en-us/library/dd489432.aspx
[Summary]
In this chapter, you have seen how to define and control transactions in the WCF client programs and services. A program can create an existing transaction list, or instantiate the transactionscope object with appropriate parameters to create a new transaction. Transactions can flow from the client to the client over the network. You can use the servicebehavior feature class and operationbehavior feature class to specify the transaction requirements in terms of service contracts and service operations. Execute the operationcontext. Current. settransactioncomplete method on the operation of the WCF Service to indicate that the transaction can be committed. Applications can call the complete method of the transactionscope object to complete transactions.
You have learned how to configure the WCF Service and client programs to include transaction information in the soap messages sent and received by them. You also learned how transactions affect the design of the WCF Service.
Finally, you can see how to use the transactedreceivescope activity in the workflow service to implement transactions. Transactedreceivescope activity is used to implement transactions with shorter running time. If the service needs to support operations that run for a long time, use the compensableactivity activity that defines the compensation logic to avoid locking resources for a long time.