Atomic transaction for WCF service and local database - wcf

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.

Related

NServiceBus and WCF, how do they get along?

Simplified... We are using NServiceBus for updating our storage.
In our sagas we first read data from our storage and updates the data and puts it back again to storage.The NServicebus instance is selfhosted in a windows service. Calls to storage are separated in its own assembly ('assembly1').
Now we will also need synchronous read from our storage through WCF. In some cases there will be the same reads that were needed when updating in sagas.
I have my opinion quite clear but maybe I am wrong and therefore I am asking this question...
Should we set up a separate WCF service that is using a copy of 'assembly1'?
Or, should the WCF instance host nservicebus?
Or, is there even a better way to do it?
It is in a way two endpoints, WCF for the synchronous calls and the windows service that hosts nservicebus (which already exists) right now.
I see no reason to separate into two distinct endpoints in your question or comments. It sounds like you are describing a single logical service, and my default position would be to host each logical service in a single process. This is usually the simplest approach, as it makes deployment and troubleshooting easier.
Edit
Not sure if this is helpful, but my current client runs NSB in an IIS-hosted WCF endpoint. So commands are handled via NSB messages, while queries are still exposed via WCF. To date we have had no problems hosting the two together in a single process.
Generally speaking, a saga should only update its own state (the Data property) and send messages to other endpoints. It should not update other state or make RPC calls (like to WCF).
Before giving more specific recommendations, it would be best to understand more about the specific responsibilities of your saga and the data being updated by 'assembly1'.

BIztalk - keeping a session key in an API

I have an API that has port type with multiple functions.
From those functions I need the logging operation and synchronize operation.
The problem is that BizTalk doesn't save session from the logging operation and thus not allowing me to perform the synchronize operation.
the API in question is a SVC WS which I generated from WCF consume adapter.
Does anyone has an idea how can I achieve the synchronize operation to work in the same session of the logging operation.
p.s.
The Logging operation doesn't return a session key it's returning only a status code
Unfortunately, that scenario is not supported by BizTalk Server, at least with the our of the box bindings.
All Send Operations are sessionless.
But, there are several ways to maintain a session. Ask the service provider how they're doing it and there might be a way to replicate that with BizTalk.

Transactions with WCF DataService and DataServiceContext around multiple additions/updates

I have a WCF service that exposes a database using System.Data.Services.DataService and a generated client proxy that consumes this service using a System.Data.Services.Client.DataServiceContext.
What I need to be able to do is make multiple additions/changes to the DataServiceContext on the client side but have these changes performed as a single transaction.
I thought of the following possibilities for accomplishing this but am unsure if these would be correct or not:
Delay calling SaveChanges() until all the required additions/modifications have been made and are successful. If any of the operations fails, somehow undo all the changes made so far so that the next time SaveChanges() is called, none of modifications will be sent to the server. (I'm not sure if even on the client side everything was successful before calling SaveChanges() if something goes wrong on the server side the server will treat a single SaveChanges() call as a transaction since it actually sends a separate POST request for each modification)
Use batch updates (I'm not sure if the server can or will handle the multiple operations within a single batch update request as a single transaction or not)
Somehow use TransactionScope (still not sure if doing this I would be able to call SaveChanges() after each update and the whole set of operations would be treated as a single transaction because they were all in the scope of the TransactionScope or if I would need to call SaveChanges() only once when done, which is basically the same situation as 1. but with the addition of the TransactionScope)
I have seen other questions similar to this here and here. The second question seems to imply that this is not possible conceptually due to the nature of a RESTful service, but I am wondering if it is still possible technically using WCF specifically.
It is possible to do this using WCF Data Services - take a look at Batch processing: WCF Data Services batch processing

WCF basicHttpBinding: Rollback when reply to client fails

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.

WebHttpBinding and Callbacks

I have asp.net site where I call my WCF service using jQuery.
Sometimes the WCF service must have an ability to ask user with confirmation smth and depend on user choice either continue or cancel working
does callback help me here?
or any other idea appreciated!
Callback contracts won't work in this scenario, since they're mostly for duplex communication, and there's no duplex on WebHttpBinding (there's a solution for a polling duplex scenario in Silverlight, and I've seen one implementation in javascript which uses it, but that's likely way too complex for your scenario).
What you can do is to split the operation in two. The first one would "start" the operation and return an identifier and some additional information to tell the client whether the operation will be just completed, or whether additional information is needed. In the former case, the client can then call the second operation, passing the identifier to get the result. In the second one, the client would again make the call, but passing the additional information required for the operation to complete (or to be cancelled).
Your architecture is wrong. Why:
Service cannot callback client's browser. Real callback over HTTP works like reverse communication - client is hosting service called by the client. Client in your case is browser - how do you want to host service in the browser? How do you want to open port for incoming communication from the browser? Solutions using "callback like" functionality are based on pooling the service. You can use JavaScript timer and implement your own pooling mechanism.
Client browser cannot initiate distributed transaction so you cannot start transaction on the client. You cannot also use server side transaction over multiple operations because it requires per-session instancing which in turn requires sessinoful channel.
WCF JSON/REST services don't support HTTP callback (duplex communication).
WCF JSON/REST services don't build pooling solution for you - you must do it yourselves
WCF JSON/REST services don't support distributed transactions
WCF JSON/REST services don't support sessionful channels / server side sessions
That was technical aspect of your solution.
Your solution looks more like scenario for the Workflow service where you start the workflow and it runs till some point where it waits for the user input. Until the input is provided the workflow can be persisted to the database so generally user can provide the input several days later. When the input is provided the service can continue. Starting the service and providing each needed input is modelled as separate operation called from the client. This is not usual scenario for something called from JavaScript but it should be possible because you can write custom WebHttpContextBinding to support workflows. It will still not achieve the situation where user will be automatically asked for something - that is your responsibility to find when the popup should appear and handle it.
If you leave standard WCF world you can check solutions like COMET which provides AJAX push/callback.