Is there a way to run EF Core RC2 tools from published DLL?

后端 未结 5 1821
抹茶落季
抹茶落季 2021-02-07 03:26

After publishing a .Net Core RC1 application, commands specified in the project.json had corresponding .cmd files created for them which could be executed after deployment (e.g.

5条回答
  •  傲寒
    傲寒 (楼主)
    2021-02-07 03:45

    I ended up in the same problem on a project but for several reasons I don't want migrations to run automatically on application boot.

    To solve it I updated Program.cs to take two arguments (full code is listed below)

    • --ef-migrate, to apply all pending migrations, and
    • --ef-migrate-check, to validate if all migrations have been applied

    If arguments are present then the EF actions are applied and the program exits, otherwise the web application is launched.

    Please note that it depends on the Microsoft.Extensions.CommandLineUtils package to ease the command line parsing.

    For octopus deploy one can then publish the package twice to seperate locations - one for running migrations and the other for webhosting. In our case, we added a "post deploy powershell script" with the content

    $env:ASPNETCORE_ENVIRONMENT="#{Octopus.Environment.Name}"
    dotnet example-app.dll --ef-migrate
    

    In a docker context it would work perfectly too

    docker run -it "example-app-container" dotnet example-app.dll --ef-migrate
    

    Full Program.cs excluding namespace and usings:

    //Remember to run: dotnet add package Microsoft.Extensions.CommandLineUtils
    public class Program
    {
        public static void Main(string[] args)
        {
            var commandLineApplication = new CommandLineApplication(false);
            var doMigrate = commandLineApplication.Option(
                "--ef-migrate",
                "Apply entity framework migrations and exit",
                CommandOptionType.NoValue);
            var verifyMigrate = commandLineApplication.Option(
                "--ef-migrate-check",
                "Check the status of entity framework migrations",
                CommandOptionType.NoValue);
            commandLineApplication.HelpOption("-? | -h | --help");
            commandLineApplication.OnExecute(() =>
            {
                ExecuteApp(args, doMigrate, verifyMigrate);
                return 0;
            });
            commandLineApplication.Execute(args);
        }
    
        private static void ExecuteApp(string[] args, CommandOption doMigrate, CommandOption verifyMigrate)
        {
            Console.WriteLine("Loading web host");
            //
            // Please note that this webHostBuilder below is from an older 
            // dotnet core version. Newer dotnet cores have a simplified version
            // Use that instead and just take the command line parsing stuff with you
            var webHost = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup()
                .Build();
    
            if (verifyMigrate.HasValue() && doMigrate.HasValue())
            {
                Console.WriteLine("ef-migrate and ef-migrate-check are mutually exclusive, select one, and try again");
                Environment.Exit(2);
            }
    
            if (verifyMigrate.HasValue())
            {
                Console.WriteLine("Validating status of Entity Framework migrations");
                using (var serviceScope = webHost.Services.GetRequiredService().CreateScope())
                { 
                    using (var context = serviceScope.ServiceProvider.GetService())
                    {
                        var pendingMigrations = context.Database.GetPendingMigrations();
                        var migrations = pendingMigrations as IList ?? pendingMigrations.ToList();
                        if (!migrations.Any())
                        {
                            Console.WriteLine("No pending migratons");
                            Environment.Exit(0);
                        }
    
                        Console.WriteLine("Pending migratons {0}", migrations.Count());
                        foreach (var migration in migrations)
                        {
                            Console.WriteLine($"\t{migration}");
                        }
    
                        Environment.Exit(3);
                    }
                }
            }
    
            if (doMigrate.HasValue())
            {
                Console.WriteLine("Applyting Entity Framework migrations");
                using (var serviceScope = webHost.Services.GetRequiredService().CreateScope())
                {
                    using (var context = serviceScope.ServiceProvider.GetService())
                    {
                        context.Database.Migrate();
                        Console.WriteLine("All done, closing app");
                        Environment.Exit(0);
                    }
                }
            }
    
            // no flags provided, so just run the webhost
            webHost.Run();
        }
    }
    

提交回复
热议问题