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!

Entity Framework 6 Change Tracking POCOs vs nHibernate

Let me warn you that this post is kind of a rant. Entity Framework is on version 6 and Code First with POCOs still can’t track changes on detached object graphs that has been sent over the wire. The scenario is quite simple:

  1. A client request an entity from the server, e.g. asp.net mvc controller renders a view.
  2. The client modifies the entity and posts it back, i.e. form post.
  3. The MVC model binder deserializes the form data to our domain model.
  4. The MVC controller should be able to update the database without first fetching the data and applying the update per property.

Well this isn’t entirely fair since we can actually do this for first level properties, but not for navigation properties, e.g. has-many relationships. NHibernate has been able to do this for ages.

A colleague working on the web team asked me for help regarding this matter and I knew that this was the case in EF4/5, but I figured they’ve implemented it by now. So I threw together a test, just to confirm that it was still as bad as I remembered it.

Let’s say our db context looks like this:

public class Db : DbContext
{
    public Db() : base("Db")
    {
        Configuration.LazyLoadingEnabled = true;
    }

    public DbSet Foos { get; set; }
    public DbSet Bars { get; set; }
}

With the following entities:

public class Foo
{
    public int Id { get; set; }
    public string Value { get; set; }
    public virtual ICollection Bars { get; set; }
}

public class Bar
{
    public int Id { get; set; }
    public string Value { get; set; }

    public int FooId { get; set; }
    public virtual Foo Foo { get; set; }
}

Our db initializer just adds one record of Foo that has a child record Bar with the values Value:

public class DbInitializer : DropCreateDatabaseAlways
{
    protected override void Seed(Db context)
    {
        context.Foos.Add(new Foo
        {
            Value = "Value", 
            Bars = new List
            {
                new Bar { Value = "Value" }
            }
        });

        context.SaveChanges();
    }
}

Our test first reads the entity and disposes the context, i.e. the graph is now detached. We make some changes to the detached graph and try to apply the changes by passing the object to SaveOrUpdate with a new db context, i.e. simulating a post from the client to our server:


[TestFixture]
public class Test
{
    [Test]
    public void TestChangeTracking()
    {
        System.Data.Entity.Database.SetInitializer(new DbInitializer());
        
        Foo foo;
        // Read and send to the client over the wire
        using (var db = new Db())
        {
            foo = db.Foos.First();
            Assert.AreEqual(1, foo.Bars.Count);
        }

        // Client changes some values
        foo.Value = "Changed";
        foo.Bars.First().Value = "Changed";

        // Post to server for an update
        using (var db = new Db())
        {
            db.Foos.AddOrUpdate(foo);
            db.SaveChanges();
        }

        // What got saved?
        using (var db = new Db())
        {
            foo = db.Foos.First();
            Console.WriteLine("Foo.Value: {0}", foo.Value);
            Console.WriteLine("Foo.Bars[0].Value: {0}", foo.Bars.First().Value);
        }

        Assert.Fail("Use nhibernate instead.");
    }
}

What got saved? Foo.Value got updated to Changed but Bars didn’t. Pretty lame if you ask me. If you insist on using EF instead of nhibernate you’ll need to fetch the record in the new db context, diff and apply the changes to it and save.

ef_update_fail

Hope they do something about this soon, until next time, have a great weekend!

Live coding 4th session – Implementing backend with WebApi2 and EF Code First

Implemented the backend as a RESTful service using WebApi2 and persistent storage to a SQL database with Entity Framework Code First. In the next session I’ll implement support for multiple users and authentication with facebook.

Live demo @ http://meetometer.azurewebsites.net/

Source code @ https://github.com/ajtowf/meetometer/

 

POST SCREENCAST EDIT

Forgot to setup automatic upgrading on application startup since I was using the package manager console in the screencast to setup the database. I added the following piece of code in commit 8be3b31:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<AppDbContext, Configuration>()); 

 

Until next time, have a nice day!

 

Keywords : VS2013, Azure, HTML5, JavaScript, AngularJS, jQuery Mobile, AmplifyJS, WebApi, EntityFramework

Entity Framework 6 Code First unreported breaking change/bug when migrating from version 5

Came a cross a nice bug in my golf score app on my season premiere round yesterday. I suddenly had a couple more strokes than I should with my HCP, although it seemed fair since it was the first round and all it didn’t make sense. I hadn’t made any (programmatic) changes to the code since the last time I played.

It took me a while to figure it out but my strokes were based on the female slope. All the custom male and female slopes were suddenly flipped, how come? I had moved the site from surftown to windows azure and with that also upgraded EF from 5 to 6 and compiled the back-end for .NET 4.5 instead of 4.0.
Without diving into golf details a golf club has one to many courses and a course has one to many tees. How many strokes a player gets from a given tee is based his HCP and is usually calculated with a formula. Unless the course has a custom slope table, then you’ll need to specify explicitly how many strokes you’ll get for a given HCP. The latter is the case on my home course, which also is the reason for me creating the app, since there is no other app that handles this well.
So my entities looked something like this (yup, I’m serializing my EF POCOs directly in my WebApi service, get over it :D)
public class Tee
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    ...
    
    [InverseProperty("TeeAsMale")]
    public virtual ICollection CustomHcpAsMale { get; set; }
    [InverseProperty("TeeAsFemale")]
    public virtual ICollection CustomHcpAsFemale { get; set; }
}
public class TeeHcp
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [JsonIgnore, IgnoreDataMember]
    public int Id { get; set; }

    public double From { get; set; }
    public double To { get; set; }
    public int Strokes { get; set; }
}
And since I haven’t mapped up the inverse property EF won’t be able to give the foreign keys good names, so the table will look like this:

ef_breaking_change_no_inverse_prop

which isn’t neat but it’s fine imho, it works, or at least it did work! Now all of the sudden CustomHcpAsMale and CustomHcpAsFemale switched places when getting the data. Since EF seemed to be confused I went ahead and explictly mapped the inverse properties, changing the code to something like this:
public class Tee
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    ...

    [InverseProperty("TeeAsMale")]
    public virtual ICollection CustomHcpAsMale { get; set; }
    [InverseProperty("TeeAsFemale")]
    public virtual ICollection CustomHcpAsFemale { get; set; }
}
public class TeeHcp
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [JsonIgnore, IgnoreDataMember]
    public int Id { get; set; }

    public double From { get; set; }
    public double To { get; set; }
    public int Strokes { get; set; }

    [JsonIgnore, IgnoreDataMember]
    public Tee TeeAsMale { get; set; }
    [JsonIgnore, IgnoreDataMember]
    public Tee TeeAsFemale { get; set; }
}
which after applying the migration changed the tables to look like this:

ef_breaking_change_with_inverse_prop

and voilá, problem solved! Once again upgrading libraries to run the latest and greatest versions for no reason bites me in the ass. I’ll try to report this to Microsoft as a breaking change, at least it was an easy fix and I figured it out quickly!
Lessons learned – don’t be lazy like me when mapping navigation properties!
Hope it helps somebody out. Peace!