我缺少哪些文件,从控制台应用程序运行迁移

本文关键字:控制台 应用程序 运行 迁移 文件 | 更新日期: 2023-09-27 18:31:44

使用实体框架 6 和有效的 PostgreSQL 数据库以及连接,我正在尝试运行 Add-MigrationUpdate-Database 命令,并通过控制台应用程序创建更新脚本。可以从控制台运行命令,因为它"只是 API 的薄包装器",请参阅我使用的示例的 SO-answer。

创建

迁移工作,创建三个常规文件,即:

Initial.cs

Initial.Designer.cs

Initial.resx

这是不适用于Update-Database的控制台应用程序。

public static void Main()
{
    // Specify the name of the database migration
    // Note: make sure to create a new name for each new migration and prefix with
    const string MIGRATION_NAME = "Initial";
    // END USER INPUT

    // Get executing path from which the location of the Update_Scripts and new 
    // Migrations can be determined.
    var executingPath = AppDomain.CurrentDomain.BaseDirectory; 

    // Write to database (PowerShell: Update-Database)
    var config = new Configuration();
    var migrator = new DbMigrator(config);
    migrator.Update(); // <= HERE IT CRASHES!
    // Now create the PostgreSQL update script.
    var scriptor = new MigratorScriptingDecorator (migrator);
    string script = scriptor.ScriptUpdate (sourceMigration: null, targetMigration: null);
    var updateScriptPath = Regex.Replace (executingPath, "Zk.Migrations/.*", 
                        "Zk/App_Data/Update_Scripts");
    File.WriteAllText (updateScriptPath + MIGRATION_NAME + ".postgresql", script);
    Console.WriteLine ("Update script {0} written to App_Data/Update_Scripts folder", MIGRATION_NAME);
}

这里的Configuration类如下所示:

public class Configuration : DbMigrationsConfiguration<ZkContext>
{
    public Configuration ()
    {
        AutomaticMigrationsEnabled = false;
        SetSqlGenerator("Npgsql", new PostgreSqlMigrationSqlGenerator());
    }
}

类来自此 GitHub 存储库PostgreSqlMigrationSqlGenerator位置。

当我尝试运行上面的更新数据库部分时,控制台应用程序在migrator.Update();崩溃。这是例外:

找不到适合指定区域性或非特定区域性的任何资源。 确保"Zk.Migrations.Initial.resources"在编译时正确嵌入或链接到程序集"Zk.Migrations"中,或者所需的所有附属程序集都是可加载的并完全签名的。

这是堆栈跟踪:

System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists (mustSuccessToKeepDatabase=
{System.Action}) in System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists
(mustSuccessToKeepDatabase={System.Action}) in
System.Data.Entity.Migrations.DbMigrator.Update (targetMigration=(null)) in
System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update () in
Zk.Migrations.MigrationsTool.Main () in/home/erwin/zaaikalender/Zk.Migrations/MigrationsTool
.cs:78

我不知道如何提供正确的资源并使脚本正常工作。我应该先运行Enable-Migrations,如果是,如何运行?希望有人能帮帮我!谢谢。

我缺少哪些文件,从控制台应用程序运行迁移

要使控制台应用正常工作,需要执行两项操作,以添加代码优先迁移、创建脚本和更新数据库:

  1. 为添加迁移时创建的.cs..resx.Designer.cs文件指定与迁移基架名称相同的名称,而不预先添加迁移的MigrationId。否则找不到文件。
  2. 右键单击资源.resx文件并选择构建操作"嵌入式资源",否则找不到资源。

控制台应用程序的完整工作脚本(使用 PostgreSqlMigrationSqlGenerator):

/// <summary>
///     Class used to generate the code migrations and SQL script based on the Models and update the database.
///     (I.e., runs PowerShell's Add-Migration and Update-Database, and creates a PostgreSQL script.)
///     See: http://stackoverflow.com/questions/20374783/enable-entity-framework-migrations-in-mono#20382226
/// 
///     Usage: run by setting Zk.Migrations as Startup project and pressing play.
/// 
///     Classes of namespace EntityFramework.PostgreSql obtained from:
///     https://github.com/darionato/PostgreSqlMigrationSqlGenerator. License is included.
/// </summary>
class MigrationsTool
{
    /// <summary>
    ///     The entry point of the program, where the program control starts and ends.
    /// </summary>
    public static void Main()
    {
        // USER INPUT /////////////////////////////////////////////////////////////////////////////////
        // Always first create a new database migration with DatabaseStep.ADD_MIGRATION,
        // and include the created files in the project and set resource file to EmbeddedResource. 
        // After creating a migration run UPDATE_DATABASE to update the database.
        const DatabaseStep step = DatabaseStep.UPDATE_DATABASE;
        // Specify the name of the database migration in case of ADD-MIGRATION.
        // Note: Make sure to create a new name for each new migration.
        //       After creating migration include the files in the folder by right clicking on 
        //       Zk.Migrations and selecting "Add files from folder". Then add the .cs, .resx and
        //       .Designer.cs files with the name specified below.
        //       Last but not least set the .resx file's build action to EmbeddedResource by right
        //       clicking on it.
        // Make sure that the Setup.postgresql script has run manually to create the database user.
        const string MIGRATION_NAME = "CalendarAndUser";
        // END USER INPUT /////////////////////////////////////////////////////////////////////////////

        // Get executing path from which the location of the Update_Scripts and new Migrations can be determined.
        var executingPath = AppDomain.CurrentDomain.BaseDirectory; 
        // Add a new migration (PowerShell: Add-Migration)
        if (step == DatabaseStep.ADD_MIGRATION) {
            // Initialize the wrapper classes around the Entity Framework PowerShell API.
            var config = new Configuration();
            var scaffolder = new MigrationScaffolder(config); 
            var migration = scaffolder.Scaffold(MIGRATION_NAME);
            // Place migration code in main project "Migrations" folder and migration scripts in "App_Data"
            var migrationsPath = Regex.Replace(executingPath, "bin/.*", "");
            // Write migrations
            File.WriteAllText (migrationsPath + MIGRATION_NAME + ".cs", migration.UserCode);
            File.WriteAllText (migrationsPath + MIGRATION_NAME + ".Designer.cs", migration.DesignerCode);
            using (var writer = new ResXResourceWriter (migrationsPath + MIGRATION_NAME + ".resx")) 
            {
                foreach (var resource in migration.Resources) 
                {
                    writer.AddResource(resource.Key, resource.Value);
                }
            }
            Console.WriteLine("EF code migration {0} written to Migrations folder...'n'n" +
                "Next step is to include the .cs, .resx and .Designer.cs file in the project" + 
                "by right clicking on the project and selecting " +  
                "'"Add files from folder.'"'n" +
                "Then right click on {0}.resx and set build action to '"EmbeddedResource'""
                , migration.MigrationId);
        }
        else if (step == DatabaseStep.CREATE_SCRIPT)
        {
            var config = new Configuration();
            var migrator = new DbMigrator(config);
            var scriptor = new MigratorScriptingDecorator(migrator);
            // Determine name of the previous run migration if exists.
            string lastMigration = migrator.GetDatabaseMigrations().LastOrDefault();
            // Get the script 
            string script = scriptor.ScriptUpdate(sourceMigration: lastMigration, targetMigration: MIGRATION_NAME);
            // Create the PostgreSQL update script based on last migration on database and 
            // current migration.
            string formattedScript = string.Format
                ("/* * * * * * * * * * * * * * * * * * * * * * *'n" +
                " *'n" +
                " * Migration:'t't{0}'n *'n" +
                " * Date and time:'t{1}'n" +
                " *'n" +
                " * * * * * * * * * * * * * * * * * * * * * * */'n'n" +
                "{2}", 
                MIGRATION_NAME, 
                DateTime.Now,
                script);
            // Write string to file in Migrations folder of main project
            var updateScriptPath = Regex.Replace(executingPath, "Zk.Migrations/.*", "Zk/App_Data/Migrations/");
            File.WriteAllText(updateScriptPath + MIGRATION_NAME + ".postgresql", formattedScript);
            Console.WriteLine("Update script {0}.postgresql written to Zk/App_Data/Migrations folder.'n" +
                "Please include the script by right clicking on the folder and selecting " + 
                "'"Add files to folder'"," +
                "'nIt is recommended to prefix the filename with the current datetime.", 
                MIGRATION_NAME);
        }
        // If a new migration is created the database can be updated. (PowerShell: Update-Database)
        else if (step == DatabaseStep.UPDATE_DATABASE)
        {
            var config = new Configuration();
            var migrator = new DbMigrator(config);
            // Write to database
            migrator.Update();
            // Show which migrations were applied.
            var migrationNames = string.Join(", ", migrator.GetDatabaseMigrations().ToArray().First());
            Console.WriteLine("Applied migration {0} to database.", migrationNames);
        }
    }
    /// <summary>
    ///     Enumeration for specifying the step in the migration.
    /// </summary>
    private enum DatabaseStep 
    {
        ADD_MIGRATION,
        CREATE_SCRIPT,
        UPDATE_DATABASE
    }
}