【问题标题】:What files am I missing wile running migrations from a console app?从控制台应用程序运行迁移时我缺少哪些文件?
【发布时间】:2014-11-28 06:32:54
【问题描述】:

使用 Entity Framework 6 和一个工作的 PostgreSQL 数据库加上连接,我正在尝试运行 Add-MigrationUpdate-Database 命令并通过控制台应用程序创建更新脚本。可以从控制台运行命令,因为它“只是 API 的薄包装”,请参阅 this SO-answer 了解我使用的示例。

migrations的创建工作,创建了三个常规文件,分别是:

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

}

PostgreSqlMigrationSqlGenerator 类来自this GitHub repository

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

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

这是堆栈跟踪:

System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists (mustSucceedToKeepDatabase=
{System.Action}) System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists
(mustSucceedToKeepDatabase={System.Action}) 在

中的 System.Data.Entity.Migrations.DbMigrator.Update (targetMigration=(null)) System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update() in
Zk.Migrations.MigrationsTool.Main () 在 /home/erwin/zaaikalender/Zk.Migrations
/MigrationsTool.cs:78

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

【问题讨论】:

    标签: c# entity-framework mono entity-framework-migrations resx


    【解决方案1】:

    要让控制台应用程序工作以添加代码优先迁移、创建脚本和更新数据库,需要做两件事:

    1. 为添加迁移时创建的.cs..resx.Designer.cs 文件指定与迁移脚手架名称相同的名称,但不添加迁移的MigrationId。否则找不到文件。
    2. 资源.resx文件右击选择BuildAction“EmbeddedResource”,否则找不到资源。

    控制台应用程序的完整工作脚本(使用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
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多