I am using WCF to Access My BL and DAL. I want to handle transactions from client not from the BL.
But when I use TransactionScope on client side, the transaction does not work correctly. Data is saved if the transaction is aborted or an exception is thrown.
When I use TransactionScope in BL it works well. My problem is that I want to handle transactions from consumer applications not from service. Is there any way to do That?
Any Suggestion? Please Help.
http://www.codeproject.com/Articles/690136/All-About-TransactionScope
There can only be two problem
The transaction flow is not set for bindings
Or using a binding that does not support distributed transaction
Related
I want to wrap a WCF external web service call and and a local database call (nhibernate) in one atomic transaction.
Is this even possible?
At the moment I am doing the following:
Perform update on local database.
Perform update on web service.
If web service call is successful commit local changes to database.
But what happens if it fails on commit?
I am assuming by external web service you mean a service which is exposed across the public web.
If the external service supports WS-Atomic Transaction, then yes it's possible to propagate a local transaction across to the service.
However, it's questionable if this approach is wise, unless the external service is also wcf over wsHttpBinding.
If the external service is non-wcf then it's likely that there will be considerable pain involved in integration; although WS-AT is designed for inter-operability, in practice there will almost certainly be variation in how the protocol has been interpreted by the different vendors, which could lead to the client and service being effectively non-inter-operable.
But what happens if it fails on commit?
As an alternative solution I would consider a compensatory pattern for this problem. As an example:
Update DB
Call service
If service call success, commit DB
If service call failure, do not commit DB
The benefit here is that system consistency can be provided in a single place. However, your problem now becomes how to tell if the call was successful or not.
Unfortunately, when you make a service call it's always possible for the call to return failure but actually succeed. A good example of this is service time-out.
How do you actually tell if you call failed? The only way is to perform a lookup against the remote resource to work out if the state of the system includes your update.
I need to coordinate a transaction between several SOAP services implemented in WCF. I know I can use the WS-Atomic transaction or oleTransactions.
For some technical reasons, I cannot make any use of the MSDTC. Is there a way I can coordinate a transaction between services without using the MSDTC?
Thanks!
Can't we make WCF to manage transactions without implicitly using MSDTC.
i.e. The wcf application should manage transactions even when I disable the Distributed Transaction Co-ordinator.
Isn't is possible.
You need to visit this link:
Configure MS DTC Component Services for WCF Transactions
I am exposing a WCF service through a basicHttpBinding that executes several operations on a database.
I want to guarantee that if the client does not receive the reply the database operations are rolled back (without any transaction flow through WCF).
E.g. the client calls the "DoX" method which executes on the server but before it is finished the client crashes. The database operations should then be rolled back as soon as the reply can not be send to the client.
Is there any way to do that? Will the [OperationBehavior(TransactionScopeRequired=true)] attribute work in such a manner? Is there a possibility to handle communication errors on the server side?
Update 1:
It seems [OperationBehavior(TransactionScopeRequired=true)] commits the transaction before the reply is send to the client and thus can not be used to perform a rollback if the client does not receive the reply.
Update 2:
To state it clearly again, I do not have the need for the transaction to interact in any way with the client side. The client should neither know of the transaction, have the ability to cancel or commit it, nor should any transaction flow through the binding. The only place I want the transaction to rollback is on the server side if the transport channel can not deliver the message to the receiving client. With the case of TCP/IP this information should be readily available to the server. (No ACK of the TCP packet send back to the client)
So a hypothetical execution flow on the server side (notice the lack of client side) should be:
Receive client request
Start transaction
Execute all logic inside the service operation
Send reply back to client
if (reply.failedToReceive) { transaction.Rollback() } // due to a failing TCP/IP transmission
There is no easy answer to this question. You are asking for a behaviour that is implemented in WS-* but done using basic SOAP. I think your only option if you REALLY can't switch to wsHttpBinding or use duplex as suggested by #Trevor Pilley is to try to mimic the behaviour of WS-Transaction in your own custom protocol based on basic SOAP.
You should be able to get some simplification over the full WS-Transaction specification because
You will probably only need to support transactions over a single service - you will not be doing a distributed transaction over several independent services
You will not need to support both short a transactions (WS-AtomicTransaction) as well as long running transactions (WS-BusinessActivity) probaby atomic transactions would do
You would not need to support any kind of extensibility model (WS-Coordination)
You would not need to implement a discovery/metadata model that describes the protocol (e.g. like WSDL) because you would be coding the protocol behaviour directly into the client and service.
However, you would probably need elements of both WS-Coordination and WS-AtomicTransaction. This is not a simple task by any means and it will be easy to miss something subtle that could cause either rollbacks to not happen or (just as bad) to destroy the performance of your service by having long duration locks all over your database due to crashed clients.
Like I say, this is a complex behaviour and if you cannot use ready-made, standardised protocols, there is no simple answer.
I imagine the following WCF service usage: (of a cash acceptor)
Service Consumer 1 Service Consumer 2
cashAcceptorService.BeginTransaction(); cashAcceptorService.StopDevice();
//this should throw exception: device is locked / used in a transaction
cashAcceptorService.AcceptMoney();
cashAcceptorService.EndTransaction();
Service Consumer 1 and 2 use the same WCF single instance. I wonder if this functionality is already implemented. Do WCF transactions offer this?
How do you see this done?
If the following is true:
The service is interacting with a transactional object (eg the database)
The service has transaction flow enabled
Then WCF does indeed offer this.
The client can then use the TransactionScope class. Any transactions initiated on the client will flow through to the service automatically.
using(TransactionScope transactionScope = new TransactionScope())
{
// Do stuff with the service here
cashAcceptorService.AcceptMoney();
//
//
transactionScope.Complete();
}
Handling transactions in WCF tends to be an entire chapter of a book, but this should be enough information to get you on the right track.
It is always better to understand the concept of distributed transactions . I recommend to read this article http://www.codeproject.com/Articles/35087/Truly-Understanding-NET-Transactions-and-WCF-Imple
I have a WCF logging service that runs operates over MSMQ. Items are logged to a Sql Server 2005 database. Every functions correctly if used outside a TransactionScope. When used inside a TransactionScope instance the call always causes the transaction to be aborted. Message = "The transaction has aborted".
What do I need to do to get this call to work inside a Transaction? Is it even possible. I've read that for a client transaction to flow across a service boundary the binding must support transaction flow, which immediately limits the bindings to only NetNamedPipeBinding, NetTcpBinding, WSHttpBinding, WSDualHttpBinding and WSFederationHttpBinding.
I'm not intimately knowledgeable about MSMQ, but there's a really good blog post series by Tom Hollander on MSMQ, IIS and WCF: Getting them to play nicely - in part 3 which is the link provided Tom talks about getting transactional.
MSMQ can be transactional - or not. And in WCF, you can decorate both the service contract as well as individual operation contracts (methods) with transaction-related attributes, such as whether to allow, disallow, or require a transaction context.
As far as I understand, in your setup, you don't want the MSMQ part to be transactional - but you should be able to use it even if an ambient transaction is present. In this case, you need to add the TransactionFlow="ALlowed" to your operation contract like this:
[ServiceContract]
public interface ILoggingService
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void LogData(......);
}
That should do it!
Marc
Sorry for the needless question...
I have solved my problem. I needed to place
[TransactionFlow(TransactionFlowOption.Allowed)]
on the operation in the service contract and then
[OperationBehavior(TransactionScopeRequired=true)]
on the implementation of the contract (the service itself).
Works a treat.