Asp.Net core 2.0: Detect Startup class invoked from migration or other ef operation

.net-core .net-core-2.0 asp.net-core entity-framework-core

Question

At the current moment all default Startup.cs flow executed on every db related operation like droping db, adding migration, updating db to migrations, etc.

I have heavy app specific code in Startup which need to be invoked only if application run for real. So how could I detect that Startup class run from migration or other database related dotnet command.

1
9
8/15/2017 8:58:45 PM

Accepted Answer

Well, as it was already noticed in comment to a question there is a IDesignTimeDbContextFactory interface which need to be implemented to resolve DbContext at design time.

It could look somewhat like this:

public static class Programm{
    ...
    public static IWebHost BuildWebHostDuringGen(string[] args)
    {
            return WebHost.CreateDefaultBuilder(args)
                .UseStartup<StartupGen>()  // <--- I'm just using different Startup child there where could be less complex code
                .UseDefaultServiceProvider(options => options.ValidateScopes = false).Build();
    }
}

public class DbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
    {   
        public MyDbContex CreateDbContext(string[] args)
        {
            return Program.BuildWebHostDuringGen(args).Services.GetRequiredService<MyDbContext>();
        }
    }

However, due to some unclear reasons (I asked guys from Microsoft, but they don't explain this to me) dotnet currently on every operation implicitly call Programm.BuildWebHost even if it's private - that's the reason why standard flow executed each time for the question's author. Workaround for that - Rename Programm.BuildWebHost to something else, like InitWebHost

There is an issue created for that, so maybe it will be resolved in 2.1 release on in future.

7
8/18/2017 8:03:21 AM

Popular Answer

The documentation is still a bit unclear as to why this occurs. I've yet to find any concrete answer as to why it runs Startup.Configure. In 2.0 it's recommend to move any migration/seeding code to Program.Main. Here's an example by bricelam on Github.

public static IWebHost MigrateDatabase(this IWebHost webHost)
{
    using (var scope = webHost.Services.CreateScope())
    {
        var services = scope.ServiceProvider;

        try
        {
            var db = services.GetRequiredService<ApplicationDbContext>();
            db.Database.Migrate();
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred while migrating the database.");
        }
    }

    return webHost;
}

public static void Main(string[] args)
{
    BuildWebHost(args)
        .MigrateDatabase()
        .Run();
}


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow