예제 #1
0
        /// <summary>
        /// Execute the migration tool
        /// </summary>
        /// <param name="generate">Set to true to generate the EF data model files</param>
        /// <param name="configFile">Set to use an explicit configuration file</param>
        /// <param name="secondsToRetryConnection">How many seconds to retry a DB connection until throwing an error (0 = disabled)</param>
        /// <returns></returns>
        public static int Main(bool generate = false, FileInfo configFile = null, int secondsToRetryConnection = 0)
        {
            var configBuilder = new ConfigurationBuilder()
                                .SetBasePath(Environment.CurrentDirectory);

            if (configFile != null)
            {
                configBuilder
                .AddJsonFile(Path.Combine(configFile.DirectoryName, "appsettings.json"), true)
                .AddJsonFile(configFile.FullName, optional: false);
            }
            else
            {
                configBuilder
                .AddJsonFile("appsettings.json", true)
                .AddJsonFile($"appsettings.{Environment.MachineName}.json", optional: true);
            }

            IConfiguration config = configBuilder
                                    .AddEnvironmentVariables()
                                    .Build();

            try
            {
                Console.WriteLine("DATABASE MIGRATION");
                Console.WriteLine();

                string baseDirectory = config["BaseDirectory"];

                if (!Path.IsPathRooted(baseDirectory) && configFile != null)
                {
                    // Base it off the config file
                    baseDirectory = Path.GetFullPath(Path.Combine(configFile.DirectoryName, baseDirectory));
                }

                if (!Directory.Exists(baseDirectory))
                {
                    throw new ArgumentException("Base directory invalid");
                }

                Console.WriteLine($"Base directory: {Path.GetFullPath(baseDirectory)}");

                if (!Directory.Exists(Path.Combine(baseDirectory, config["MigrationDirectory"])))
                {
                    throw new ArgumentException("Migration directory invalid");
                }

                var migrator = new Migrator(
                    baseConnectionString: config["BaseConnectionString"],
                    migrationDirectory: Path.Combine(baseDirectory, config["MigrationDirectory"]));

                if (generate)
                {
                    // Generate
                    migrator.CreateMigrationScripts(
                        templateDatabaseName: config["TemplateDatabaseName"],
                        migrationDatabaseName: config["MigrationDatabaseName"],
                        createScriptFileName: Path.Combine(baseDirectory, config["CreateScript"]));

                    if (!string.IsNullOrEmpty(config["ModelsDirectory"]))
                    {
                        // Generate models for the current destination database
                        Console.WriteLine($"Generate EF.Core data models in folder {config["ModelsDirectory"]} for context {config["ContextName"]} from the template database");
                        ScaffoldGenerator.ExecuteScaffold(baseDirectory, config["BaseConnectionString"], config["TemplateDatabaseName"], config["ModelsDirectory"], config["ContextName"]);
                    }
                }
                else
                {
                    // Migrate (default)
                    var watch = Stopwatch.StartNew();
                    while (true)
                    {
                        try
                        {
                            migrator.MigrateDatabase(config["MigrationDatabaseName"]);
                        }
                        catch (System.Data.SqlClient.SqlException ex)
                        {
                            if (secondsToRetryConnection > 0 && watch.Elapsed.TotalSeconds < secondsToRetryConnection)
                            {
                                Console.WriteLine($"Failed to connect to SQL: {ex.Message}, retrying");

                                Thread.Sleep(2000);
                                continue;
                            }

                            throw;
                        }

                        break;
                    }
                }

                return(0);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception: {ex.Message}");
                Console.WriteLine($"Exception: {ex}");

                return(1);
            }
        }