Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 528
silent_coder Avatar asked Aug 15 '17 13:08

silent_coder


2 Answers

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.

like image 76
Ph0en1x Avatar answered Oct 27 '22 21:10

Ph0en1x


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();
}
like image 33
Travis Boatman Avatar answered Oct 27 '22 22:10

Travis Boatman