Saturday, 19 January 2013

Entity Framework Migrations, seeding and server farms

Entity Framework Migrations offers a way to evolve your database schema over time. The schema is fine, but what about your actual data? You may have configuration settings in the database and how do you handle it when you need to add a new configuration setting?
With Entity Framework Migrations enabled, your seeder function will run every time you restart your application, so as long as your new configuration setting is in your seeder all will be well. Well, sort of... How do you avoid adding a duplicate row the next time your application is restarted? A simple answer with Code First would be something like;

if (!context.Entries.Any(e => e.Value.Equals(value)))
{
    var entry = new Entry() { // initialize };
    context.Entries.Add(entry);
    context.SaveChanges();
}


That works well until you have more than one server as you may then have two or more servers running this code at the same time.
Personally I happen to use Azure so I always have at least two servers.

In Entity Framework 5 you have the AddOrUpdate extension method but you may not always want to update stuff - sometimes you may want to insert it if it doesn't exist and otherwise leave it alone. Or you may be using EF4.

The key to handling this is to obtain a table lock before you check and insert. Now, table locks are normally very bad things because it stops other users from reading from the table – which is of course what you want in this scenario – but you do need to carefully consider any adverse effect this may have on your application. Tom Peplow has a a very good article on how to achieve table locks with Entity Frameworks. I have adapted his approach for use specifically when seeding with Code First.

For the examples below, I am imagining an entity called “Entry” and the underlying database table is called “Entries”. Entry has a “Value” property which is the one I want to be unique in my example, but just replace the lambdas as required for your needs.

The code below will obtain a table lock before checking and inserting;

using (var scope = new TransactionScope(
        TransactionScopeOption.Required, 
        new TransactionOptions() 
            { IsolationLevel = IsolationLevel.ReadCommitted })                            )
    {
    context.Database.ExecuteSqlCommand(
        "select 1 from Entries with (tablockx, holdlock) where 0 = 1");
    if (!context.Entries.Any(e => e.Value.Equals(value)))
    {
        var entry = new Entry() { // Initialize };
        context.Entries.Add(entry);
        context.SaveChanges();
    }
    
    scope.Complete();
}


If you find yourself needing to do this a lot, you could create an extension method like this, which can work for any entity and table;

public static class DbContextExtensions
{
    public static bool UniqueInsert<TContext, TEntity>(
        this TContext context, 
        Func<TContext, IDbSet<TEntity>> dbSetAccessor, 
        TEntity entity, 
        Func<TEntity,bool> areSame, 
        string underlyingTableName) 
        where TContext : DbContext 
        where TEntity : class
    {
        using (var scope = new TransactionScope(
                  TransactionScopeOption.Required, 
                  new TransactionOptions() 
                     { IsolationLevel = IsolationLevel.ReadCommitted }))
        {
            try
            {
                context.Database.ExecuteSqlCommand(
                    String.Format("select 1 from {0} with (tablockx, holdlock) where 0 = 1", 
                    underlyingTableName));
                var set = dbSetAccessor(context);
                if (!set.Any(areSame))
                {
                    set.Add(entity);
                    context.SaveChanges();
                    return true;
                }
                return false;
            }
            finally
            {
                scope.Complete();                    
            }
        }
    }
}

And call it like this:

var entry = new Entry() { // initialize };
context.UniqueInsert(
    c => c.Entries, 
    entry , 
    dbEntity => dbEntity.Value.Equals(entry.Value), 
    "Entries");

Thursday, 10 January 2013

How to Mock RestSharp.ExecuteAsync

It took me a while to figure out how to Mock RestSharp’s ExecuteAsync method for unit testing purposes. Once you realise that ExecuteAsync takes a callback which is called when the REST call completes it all becomes reasonably straightforward, using Mocks Callback function;
Mock<IRestClient> restClient = new Mock<IRestClient>();
            restClient.Setup(c => c.ExecuteAsync<MyResult>(
                    Moq.It.IsAny<IRestRequest>(), 
                    Moq.It.IsAny<Action<IRestResponse<MyResult>, RestRequestAsyncHandle>>()))
                .Callback<IRestRequest, Action<IRestResponse<MyResult>, RestRequestAsyncHandle>>((request, callback) =>
                {
                    var responseMock = new Mock<IRestResponse<MyResult>>();
                    responseMock.Setup(r => r.Data).Returns(new MyResult() { Foo = "Bar" });
                    callback(responseMock.Object, null);
                });

In my scenario I wanted to use the built-deserialization and return a “MyResult".
This means that ExecuteAsync takes two parameters:
  • An IRestRequest
  • A callback, which is an Action<IRestResponse<AuthorisationResponse>, RestRequestAsyncHandle>

    That is just the callback you pass in and it is a delegate that takes two parameters, namely the IRestResponse and a RestRequestAsyncHandle.
When you are running this for real, RestSharp will execute your IRestRequest and then call your callback with the result. So in our Unit test, we can use Mock’s Callback feature to call your callback straight away. To your code that will just look like the website responded really quickly.

When I actually call the callback function, I also use Mock to mock the IRestResponse and just configure that mock to return a concrete instance of MyResult.

EDIT 9 November 2013

A fuller example:

public class Sud
{
    private IRestClient client;

    public Sud(IRestClient client)
    {
        this.client = client;
    }

    public MyResult Foo()
    {
        // NOTE: This code is obviously stupid; it just blocks the thread until the async task completes, which is rather pointless.
        // It's just an example :)
        MyResult result = null;
        var request = new RestRequest();
        var blocker = new AutoResetEvent(false);

        this.client.ExecuteAsync<MyResult>(
            request, 
            response =>
            {
                result = response.Data;
                blocker.Set();
            });
        blocker.WaitOne();
        return result;
    }
}

public class MyResult
{
    public string Name { get; set; }
}

[TestFixture]
public class Tests
{
    [Test]
    public void TestFoo()
    {
        Mock<IRestClient> restClient = new Mock<IRestClient>();
        restClient.Setup(c => c.ExecuteAsync<MyResult>(
                Moq.It.IsAny<IRestRequest>(),
                Moq.It.IsAny<Action<IRestResponse<MyResult>, RestRequestAsyncHandle>>()))
            .Callback<IRestRequest, Action<IRestResponse<MyResult>, RestRequestAsyncHandle>>((request, callback) =>
            {
                var responseMock = new Mock<IRestResponse<MyResult>>();
                responseMock.Setup(r => r.Data).Returns(new MyResult() { Name = "Billy Bob" });
                callback(responseMock.Object, null);
            });

        var Subject = new Sud(restClient.Object);

        var result = Subject.Foo();

        Assert.IsNotNull(result);
        Assert.AreEqual("Billy Bob", result.Name);
    }
}