3
votes

I would like to automatically run a database migration on application start in ASP.NET Core 2.0 and EntityFramework Core 2.0.

I have found Run database migrations using Entity Framework core on application start. However, my connection strings are stored in the environment variables so they would not be found until the .AddEnvironmentVariables() are called in the Configure method.

How to call the db.Database.Migrate() or how to properly do the database migration (in Azure Web App) via Continuous Deployment and staging environments?

public class Startup
{
    private IConfigurationRoot Configuration { get; set; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddDbContext<ClientContext>(options => options.UseSqlServer(this.Configuration.GetConnectionString("AppService")));
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMvc();

        this.Configuration = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables()
            .Build();
    }

    // public void Configure(IApplicationBuilder app, ClientContext db)
    // {
    //     db.Database.Migrate();
    // }
}
1
Why not just call db.Database.Migrate() at the end of the Configure() method? After connection strings are set. - Stephen Wilson
If I add the ClientContext db parameter to the Configure method, the ClientContext will get instantiated before the Configure call is made. The ClientContext gets the options as a constructor parameter which tries to retrieve the AppService connection string before the Configuration object is configured (or event instantiated). Or is my understanding wrong? - alik

1 Answers

3
votes

Based on you comment above I would try this:

public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
{
    app.UseMvc();

    this.Configuration = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables()
        .Build();

    var db = serviceProvider.GetService<ClientContext>();
    db.Database.Migrate();
}

This is manually resolving the ClientContext after the Environment variables have been set up and therefore it won't fail the parameter injection.

EDIT: The error you're getting can be resolved by following the steps in this SO question