4

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();
    // }
}
2
  • 1
    Why not just call db.Database.Migrate() at the end of the Configure() method? After connection strings are set. Commented Jul 19, 2017 at 13:19
  • 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? Commented Jul 19, 2017 at 13:22

1 Answer 1

4

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

Sign up to request clarification or add additional context in comments.

4 Comments

I guess that the ClientContext life time is managed by the runtime so there is no need to add "using" statement, right?
I am getting Cannot resolve scoped service 'AppService.ClientContext' from root provider..
See my edit above, no point me re-writing out those steps as well :-)
The only thing I am not very happy of is that the app needs to work under a full sql admin to make this work. But that is another issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.