Posts

Connection leaks when using async/await with Transactions in WCF

If you’re getting “The current TransactionScope is already complete” from service calls that don’t even consume transactions, you’ll probably want to read/see this.

Screencast and Code

The code can be found on github, https://github.com/ajtowf/dist_transactions_lab, one change I did since the recording is that we don’t create the nhibernate factory with each call, we now use a singleton SessionManager instead. Also we’re adding the convention to the factory to never load lazy so that our Item entity don’t need to have virtual properties, which makes it easier to switch between OR-mapper implementations.

Leaking Connections

In a fairly complex distributed enterprise system we were getting some strange The current TransactionScope is already complete errors. We used transactions frequently but we saw this on calls that wasn’t even supposed to run within an transaction.

After trying almost everything we got a hint from a nhibernate analyzer product that we shouldn’t consume a nhibernate session from multiple threads since it’s not thread safe.

If you use await, that’s exactly what happens. Turns out entity framework has the same problem.

The following code in your service will leak connections if the awaited method or service call uses a database connection with EntityFramework or NHibernate.

    [OperationBehavior(TransactionScopeRequired = true)]
    public async Task CallAsync()
    {
        using (var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
        {
            await _service.WriteAsync();
            ts.Complete();
        }
    }

Why Tasks in the Service Contract at all?

The lone reason for our service contracts being task based is that we use the same interface to implement our client-side proxies, which is neat, but the service doesn’t need use await because of that. This will work for instance:

    [OperationBehavior(TransactionScopeRequired = true)]
    public Task CallAsync()
    {
        // Do synchronous stuff
        return Task.FromResult(true);
    }

or (don’t like this one though)

    [OperationBehavior(TransactionScopeRequired = true)]
    public Task CallAsync()
    {
        // Remember to copy the OperationContext and TranactionScope to inner Task.
        return Task.Run(() =>
        {
            // Do synchronous stuff
        });          
    }

Oh, you don’t want to return a Task if you’re not doing anything async? Do this then:

    [OperationBehavior(TransactionScopeRequired = true)]
    public async Task CallAsync()
    {
        // Do synchronous stuff
    }

What about the warning? Turn it off with #pragma.

     [OperationBehavior(TransactionScopeRequired = true)]
#pragma warning disable 1998
     public async Task CallAsync()
#pragma warning restore 1998
        {            
            // Do synchronous stuff        
        }

You’ll probably want to wrap the entire service class with that pragma disable.

Solution

The main take away here is to simply not use async/await in your service code if you’re awaiting methods or service calls that will use database connections. The following refactoring solves the problem:

    [OperationBehavior(TransactionScopeRequired = true)]
    public Task CallAsync()
    {
        _service.WriteAsync().Wait();
        return Task.FromResult(true);
    }

As always, until next time, have a nice day!

Distributed Transactions in WCF with async and await

TL;DR?

See my screencast explaining problem instead:

Problem

When flowing a transaction from a client to a service Transaction.Current becomes null after awaiting a service to service call.

Unless of course you create a new TransactionScope in your service method as follows:

    [OperationBehavior(TransactionScopeRequired = true)]
    public async Task CallAsync()
    {
        using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
        {
            await _service.WriteAsync();
            await _service.WriteAsync();            
            scope.Complete();
        }
    }

Problem UPDATE

It doesn’t even have to be a service to service call, an await to a local async method also nulls Transaction.Current. To clearify with an example

    [OperationBehavior(TransactionScopeRequired = true)]
    public async Task CallAsync()
    {
        await WriteAsync();
        // Transaction.Current is now null
        await WriteAsync();                     
    }

Why TransactionScopeAsyncFlowOption isn’t enabled by default I don’t know, but I don’t like to repeat myself so I figured I’d always create an inner transactionscope with that option using a custom behavior.

Attempted Solution

I created a Message Inspector, implementing IDispatchMessageInspector and attached it as a service behavior, code executes and everyting no problem there, but it doesn’t have the same effect as declaring the transactionscope in the service method.

    public class TransactionScopeMessageInspector : IDispatchMessageInspector
    {
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            var transactionMessage = (TransactionMessageProperty)OperationContext.Current.IncomingMessageProperties["TransactionMessageProperty"];
            var scope = new TransactionScope(transactionMessage.Transaction, TransactionScopeAsyncFlowOption.Enabled);            
            return scope;
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            var transaction = correlationState as TransactionScope;
            if (transaction != null)
            {
                transaction.Complete();
                transaction.Dispose();
            }
        }
    }

by looking at the identifiers when debugging I can see that it in fact is the same transaction in the message inspector as in the service but after the first call, i.e.

    await _service_WriteAsync();

Transaction.Current becomes null. Same thing if not getting the current transaction from OperationContext.Current in the message inspector as well so it’s unlikely that is the problem.

Is it possible to create a TransactionScope in a Custom WCF Service Behavior?

Is it even possible to accomplish this? It appears like the only way is to declare a TransactionScope in the service method, that is:

    public async Task CallAsync()
    {
        var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
        await _service.WriteAsync();
        await _service.WriteAsync();            
        scope.Complete();
    }

with the following service contract it’s obvious that we get an exception on the second service call if transaction.current became null inbetween

    [OperationContract, TransactionFlow(TransactionFlowOption.Mandatory)]
    Task WriteAsync();

Got a link to a book posing the exact same question on my stackoverflow question. The conclusion is basically that it can’t be done in a clean way. Quoting the book:

We consider the lack of parity with standard WCF behavior introduces by async service operations a design flaw of WCF…

And then a far from ideal / insane solution is proposed.

Accepted Solution for now

It seems like the only way to make this work is to create an inner transaction, if you have a better solution feel free to comment or contact me or why not answer my stackoverflow question http://stackoverflow.com/questions/34767978.

Until next time, have an excellent day!

What about WCF 4.5 and the async/await pattern?

From what I’ve heard it should be pretty smooth to produce asynchronous server/client code with .net 4.5, so let’s try it out! Defining async methods on the service contract is now a lot cleaner :

[ServiceContract]
public interface IPeopleService
{
	[OperationContract]
	Task<IList<Person>> GetPeople();
}

instead of the wcf 4.0 way which would look something like this :

[ServiceContract]
public interface IPeopleService
{
	[OperationContract(AsyncPattern=true)]
	IAsyncResult BeginGetPeople(AsyncCallback cb, object state);

	[OperationContract]
	IList<Person> GetPeople();

	[OperationContract]
	IList<Person> EndGetPeople(IAsyncResult ar);
}

the server side implementation of the operation when returning a task is straightforward :

public async Task<IList<Person>> GetPeople()
{
	Task t1 = Task.Delay(500);
	Task t2 = Task.Delay(500);
	await Task.WhenAll(t1, t2);

	return await Task.Factory.StartNew(() => people);
}

If you don’t want to await something in the method you can skip the async keyword and still return a Task as shown below, async on a method simply tells the compiler that “I’m going to await something in this method”.

public Task<IList<Person>> GetPeople()
{
	return Task.FromResult(people);
}

Anyways it’s really nice to skip the non-implemented begin/end methods on the server which was simply boiler plating in .net 4.0. For the sake of simplicity the service will be hosted in a console application and for consuming the service I’ve implemented a simple proxy that inherits ClientBase<TChannel> and implements the contract. See the code if this confuses you (which probably means that you’re a noob ;-)). The client code when working with tasks is clean and straightforward as well :

var serviceProxy = new PeopleServiceProxy("PeopleServiceEndpoint");

Task<IList<Person>> people = serviceProxy.GetPeople();
people.ContinueWith(
	x =>
		{
			foreach (Person person in x.Result)
			{
				Console.WriteLine(
					"{0} {1} born {2}",
					person.FirstName,
					person.LastName,
					person.BirthDate.ToShortDateString());
			}
		});

We can control on which thread we will continue by passing in a TaskScheduler. So far so good, so what about testing? I’m using Nunit which integrates really well with VS when using resharper. I want to write an integration test (not unit) to make sure everything works well including the WCF part since unit testing my simple service is too easy ;-) I’ll host the service in the Setup method and take it down in the teardown. A simple test then looks like :

[Test]
public void ShallBeAbleToGetDateTimeFromService()
{
	IPeopleService serviceProxy = new PeopleServiceProxy("PeopleServiceEndpoint");

	Task<IList<Person>> getPeopleTask = serviceProxy.GetPeople();
	getPeopleTask.Wait();

	IList<Person> result = getPeopleTask.Result;

	Assert.IsNotNull(result);
	Assert.AreEqual(2, result.Count);

	(serviceProxy as IDisposable).Dispose();
}

Obviously we’d use facades to call on services in a real application but the principle is the same. It doesn’t get much cleaner than this imo.

/A

Get the code here! (67KB)