1
votes

One of my WCF service operation has transaction enabled-

[OperationBehavior(TransactionScopeRequired = true)]
public Car UpdateCar(Car c)
{
}

Earlier, I was running this service with InstanceContextMode as PerCall and ConcurrencyMode as Multiple which was getting me the below error-

An unhandled exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.dll Additional information: The 'InventoryManager' service is configured with ReleaseServiceInstanceOnTransactionComplete set to true, but the ConcurrencyMode is not set to Single. The ReleaseServiceInstanceOnTransactionComplete requires the use of ConcurrencyMode.Single.

In order to solve above error, i set 'ReleaseServiceInstanceOnTransactionComplete' to false and this did the trick.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall
                 , ConcurrencyMode = ConcurrencyMode.Multiple
                 , ReleaseServiceInstanceOnTransactionComplete = false)]

Can someone please help to understand how disposing the service instance with 'PerCall' and 'Multiple' case solved this problem. What is the problem WCF thinks if I release service instance.

2

2 Answers

0
votes

These are purely design decision made by the WCF designers.

From the book programming WCF services:

The WCF architects did not trust developers to properly manage state of their sessionful service in the face of transactions. Therefore they decided to treat a sessionful transactional service as a per-call service to enforce a proper state aware programming model.

And a Percall service with ConcurrencyMode.Multiple is useless of course. At the service load time WCF verifies that if TransactionScopeRequired is true for at least one operation when ReleaseServiceOnTransactionComplete is true, the ConcurrencyMode is ConcurrencyMode.Single. That is the behaviour you are observing.

https://books.google.nl/books?id=PvNrurEhmiEC&pg=PA348&lpg=PA348&dq=per-session+transactional+services&source=bl&ots=CiDuKxG_Ox&sig=UvkgF1yTxmirsf_Zb452bW86AmQ&hl=nl&sa=X&ved=0ahUKEwiYjrX-uPrPAhWGfhoKHTgWBckQ6AEIHDAA#v=onepage&q=per-session%20transactional%20services&f=false

The designers were probably right with the decision to let WCF handle concurrency in the face of transactions. It is hard to manage your own concurrency in a service.

For instance, I had a service that also acted as a client of another service.

When changing the concurrency mode to Multiple the service would sometimes throw the exception when trying to open the client connection:

"System.InvalidOperationException: Cannot make a call on this channel because a call to Open() is in progress."

This is the kind of hard to debug kind of bugs the designers wanted to avoid (I think)

0
votes

The default implementation of Service is

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]

If there is a TransactionScope defined on any Operations on your Service implementation:

[OperationBehavior(TransactionScopeRequired = true)]
public void Method() { }

The default Service implementation will be dropped to

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

And this attribute will prevent it and will regain your PerSession semantics:

[ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete = false)]

Take note that this is necessary if you have sessionful service and atleast one TransactionScopeRequired = True, on one of your operations.