views:

767

answers:

1

Basic architecture: n physical boxes each hosting the same WCF service, sitting begind a load balancer. Each box hitting a single database infrastructure that does not support transactions - don't ask :(

So, in the data access layer of my app I need some method of distributed transactions. What are my options?

Note that clients to my system will be legacy apps communicating using basic web services (BasicHttpBinding) and shiny new WCF clients (NetTcpBinding or NetNamedPipeBinding ).


Edit 1

E.g. there will be a single call into the WCF layer on physical box 1, e.g. EditEntity(...). This call will trigger 2 writes to the database. After the first write another client calls EditEntity(...) for the same entity on a second instance of my WCF service on a second physical box. On the second box how do I know that a transaction for this particular entity is already in play?

Thanks.

+1  A: 

Not sure you've given us enough to go on, but if I'm reading correctly you're attempting to make sure you can support a transaction through your WCF service? While your DB doesn't support transactions, and your WCF endpoints sit behind a load balancer? Do I have this correct? If so....

Since your DB doesn't have transactional support, that moves to your WCF tier. This suggests a coarse level of granularity in your methods such that you can ensure a single call to your WCF service encompasses your transaction sufficiently. Don't spread a transaction across multiple WCF calls, you're asking for trouble.


UPDATE: There are strategies that can be employed with load balancers that ensure persistence among connections, but that won't help you here. If you're calling EditEntity() consecutively, and the first entry is to initiate a transaction, and the second entry is to complete a transaction...then your service is not granular enough.

Consolidate those two calls to one method, i.e. EditEntityComplete().

Is there a reason that you cannot create one method, as opposed to two?


UPDATE #2: Rephrasing the issue - a single method performs entries within a database that does not support transactions. The method in question executes a series of steps that must be completed in order. The WCF method represents opportunities for concurrency contention to violate step completion in the proper order.

With that basis, assuming you don't require any return data from the function, consider an asynchronous Queue that can log requests from the WCF endpoints. Then process the Queue from a single background process.


FINAL REVISION:

Reconsider the requirement of not changing the data store.

Given the requirements for multiple clients, need for scale, load balancing and transactional support in the data store, a final suggestion -- push to change the database. Understanding this is a static requirement, but you will expend a lot of effort trying to implement transactional support when plenty of simple database platforms will provide it for you. Trying to re-create this functionality has little upside but a lot of downside.

jro
Thanks. Your summary is correct. Problem is that the WCF tier will be distributed across multiple boxes - i.e. scaled out. I've updated my question.
ng5000
There is only 1 method. However, it is called by two different clients and each request is serviced by a different physical box.
ng5000
OK, I think I have a better understanding now. It sounded as though two consecutive calls to EditEntity() were required to complete a transaction.
jro
Thanks - but asynch queue solution is no good as the single background process is a single point of failure and doesn't scale. +1 for the effort though ;)
ng5000
Thanks for the up-vote, but single point of failure and doesn't scale? I would highly suggest reviewing queuing technologies, such as Windows MSMQ or Apache ActiveMQ. Load balancing, replication, multiple clients, it's all in there.
jro
Fair point - I was just commenting on the suggestion that a single background process takes messages of the queue, but of course there is no reason why multiple processes couldn't perform the dequeues. Thanks for all your input.
ng5000