Search code examples
.netentity-framework-coreef-core-3.1ef-core-3.0ef-core-5.0

How to run EFCore Migrate on ASP.NET start up WITH retries?


So I want to run EF migrations when the Azure app service is first started. The following code works correctly:

public class Program
{
    public static void Main(string[] args)
    {
        ...
        var host = CreateHostBuilder(args).Build();
        using (var scope = host.Services.CreateScope())
        using (var context = scope.ServiceProvider.GetService<MyContext>())
        {
             context.Database.Migrate();
        }
        host.Run();
        ...
     }
 }

However because the database is running as a serverless instance on Azure, if it is currently paused, then it needs to retry (as the first connection attempt(s) fail).

Once the service is started, for requests I have configured retries using EnableRetryOnFailure - which works as expected:

services.AddDbContext<MyContext>(options =>
    {
        options.UseSqlServer(Configuration["...."],
           sqlServerOptionsAction: sqlOptions =>
           {
               sqlOptions.EnableRetryOnFailure(
                   maxRetryCount: 5,
                   maxRetryDelay: TimeSpan.FromSeconds(5),
                   errorNumbersToAdd: null);
           });
    });

So is there something similar I can use in Program.Main() to handle app service start Migrations?

Many thanks in advance!


Solution

  • One way to solve this problem is to use Polly

    You can create a policy like:

        var migrateDbPolicy = Policy
            .Handle<Exception>()
            .WaitAndRetry(4, retryAttempt => TimeSpan.FromSeconds(retryAttempt));
    
        migrateDbPolicy.Execute(() =>
        {
            context.Database.Migrate();
        });
    

    So any code running into the execute method would be retried if the exception you have set in the policy is caught.

    Polly is a very powerful library trusted by Microsoft. The example above is a very basic one. You can apply different policies on each type of exception (Generic Exception is not really suggested). You can have different waiting times etc.

    I would suggest you spent some time and dig into it.