Asp.Net核心2.0:检测从迁移或其他ef操作调用的Startup类

时间:2017-08-15 13:39:38

标签: asp.net-core .net-core entity-framework-core .net-core-2.0

目前,在每个与数据库相关的操作上执行所有默认Startup.cs流,例如删除数据库,添加迁移,更新数据库到迁移等等。

我在Startup中有大量特定于应用程序的代码,只有在应用程序运行真实时才需要调用它。那么如何检测Startup类是从迁移还是其他与数据库相关的dotnet命令运行的。

2 个答案:

答案 0 :(得分:7)

好吧,因为在对问题的评论中已经注意到,在设计时需要实施IDesignTimeDbContextFactory接口以解析DbContext

看起来有点像这样:

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>();
        }
    }

然而,由于一些不明原因(我问微软的人,但是他们没有向我解释这一点)dotnet目前在每个操作上隐含地调用Programm.BuildWebHost即使它是私有的 - 这是每次为问题的作者执行标准流程的原因。解决方法 - 重命名 Programm.BuildWebHost 到其他地方,例如InitWebHost

有一个issue created,所以也许它将在2.1版本中解决。

答案 1 :(得分:2)

documentation对于为什么会发生这种情况仍然有点不清楚。我还没有找到任何具体的答案,为什么它运行Startup.Configure。在2.0中,recommend将任何迁移/种子代码移至Program.Main。以下是bricelam Github上的https://docs.angularjs.org/guide/interpolation示例。

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();
}