Enity Framework 6.0.0.0:无法使用基于代码的迁移生成显式迁移

时间:2014-11-05 08:14:52

标签: entity-framework-6

情况是:

  1. 每个租户db。
  2. 非自动基于代码的迁移。 dbs的初始创建也是通过Code First进行的。当前场景中没有预先存在的dbs。
  3. 在生成迁移脚本期间,确切的数据库是未知的,因为有很多。我唯一拥有的是代码 - 基于初始模型的初始迁移脚本和带有一些修改的模型。
  4. 使用初始脚本生成的现有dbs - 一切正常。以下是我重现问题的方法:
  5. 运行PS命令:Add-Migration -Name Initial -StartUpProjectName MyApp.Web -ProjectName MyApp.Migrations -ConfigurationTypeName" MyApp.Migrations.MyMigrationConfiguration" -ConnectionString"数据源=。\ SQLEXPRESS;数据库= demo-db; Trusted_Connection = False;用户ID = x;密码= x" -ConnectionProviderName" System.Data.SqlClient" - 工作正常
  6. 运行应用程序并创建数据库。停止应用程序。修改模型。
  7. 运行PS命令:Add-Migration -Name MySecondMigration -StartUpProjectName MyApp.Web -ProjectName MyApp.Migrations -ConfigurationTypeName" MyApp.Migrations.MyMigrationConfiguration" -ConnectionString"数据源=。\ SQLEXPRESS;数据库= demo-db; Trusted_Connection = False;用户ID = x;密码= x" -ConnectionProviderName" System.Data.SqlClient" - 轰隆。
  8. 微妙 - 迁移器甚至没有连接到MSSQL来检查db是否存在或者是否有dbo .__ MigrationHistory!我已经进一步关闭了MSSQL服务! - 如果我输入错误的数据库名称或者我关闭整个MSSQL服务器并不重要 - 错误是相同的并且没有建立连接。那么当它不检查数据库时,它如何知道迁移正在等待?我假设一个错误。
  9. 我已经使用初始迁移创建了__dbo.MigrationHistory。
  10. 错误:无法生成显式迁移,因为以下显式迁移正在等待处理:[201402121953301_Initial]。在尝试生成新的显式迁移之前应用挂起的显式迁移。
  11. 这是我的配置 - 没什么特别的:

    public class MyMigrationConfiguration : DbMigrationsConfiguration<MyMigrationContext>
    {
        public MyMigrationConfiguration()
        {
            AutomaticMigrationsEnabled = false;
            AutomaticMigrationDataLossAllowed = false;
            MigrationsNamespace = "---";
            MigrationsDirectory = "---";
        }
    }
    

    这是我创建dbs的方法:

     public void CreateOrUpdateDb(string DbName)
            {
                try
                {
                    string connectionString = _connectionStringProvider.GetConnectionString(DbName);
                    DbMigrationsConfiguration cfg = CreateMigrationsConfig(connectionString);
                    cfg.AutomaticMigrationsEnabled = false;
                    cfg.AutomaticMigrationDataLossAllowed = false;
                    DbMigrator dbMigrator = new DbMigrator(cfg);                              
                    dbMigrator.Update();
                }
                catch (MigrationsException exception)
                {
                    _logger.Error(string.Format("Error creating database '{0}'",DbName), exception);
                }
            }
    

    我已经搜索并阅读了我在网络上可以找到的任何内容,但大多数示例包括标准的Configuration.cs等。没有人解释为什么我应该运行Enable-Migrations,因为它创建了Configuration.cs但我自己提供了Configuration类,并且不需要这个其他类。

    这是异常堆栈:

    > System.Data.Entity.Migrations.Infrastructure.MigrationsPendingException: Unable to generate an explicit migration because the following explicit migrations are pending: [201402121953301_Initial]. Apply the pending explicit migrations before attempting to generate a new explicit migration.
       at System.Data.Entity.Migrations.DbMigrator.Scaffold(String migrationName, String namespace, Boolean ignoreChanges)
       at System.Data.Entity.Migrations.Design.MigrationScaffolder.Scaffold(String migrationName, Boolean ignoreChanges)
       at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Scaffold(MigrationScaffolder scaffolder)
       at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
       at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
       at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
       at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
       at System.Data.Entity.Migrations.Design.ToolingFacade.Scaffold(String migrationName, String language, String rootNamespace, Boolean ignoreChanges)
       at System.Data.Entity.Migrations.AddMigrationCommand.Execute(String name, Boolean force, Boolean ignoreChanges)
       at System.Data.Entity.Migrations.AddMigrationCommand.<>c__DisplayClass2.<.ctor>b__0()
    

    有没有办法强制迁移器制作脚本而不告诉我有一些待处理的迁移,即使没有?这是EF的100%错误,但我不知道如何绕过它。

1 个答案:

答案 0 :(得分:3)

我们找到了答案 - 我的聪明同事并在Reflector.

的帮助下
  1. 在EntityFramework.dll内部有类
  2. 带有方法的System.Data.Entity.Migrations.DbMigrator
  3. 脚手架(字符串migrationName,字符串@namespace,bool ignoreChanges)
  4. 调用this.GetPendingMigrations
  5. 哪个方法使用参数contextKey == NULL
  6. 在另一个类HistoryRepository.CreateHistoryQuery(HistoryContext context, string contextKey = null)上调用另一个方法
  7. 但是在这种方法中会发生这种情况

    contextKey =!string.IsNullOrWhiteSpace(contextKey)? contextKey.RestrictTo(this._contextKeyMaxLength):this._contextKey;

  8. 并且contextKey不再为null。它实际上变成了类型(YourInheritedDbMigrationConfiguration).ToString()

    问题出在哪里?问题在于

    1. 我使用两个不同的DbMigrationConfiguration类
    2. 因为迁移程序集与应用程序的核心分离
    3. 他们两个不同的“完全限定的命名类”,最后是
    4. 在dbo._MigrationHistory表中为DbMigrationHfory表生成两个不同的ContextKeys,用于生成迁移脚本。
    5. 因此,当我创建初始迁移脚本并启动站点并且站点应用脚本时,它可以,但在dbo._MigrationHistory中,ContextKey是“MyDbConigClass1”。之后,当我尝试Add-Migration使用另一个DbMigrationConfiguration类时,ContextKeys不匹配 - BOOM!

      解决方案:在我的两个配置类中添加了相同的ContextKey =“MyTenantDb”,所有内容都重新开始工作,因为类型名称不再涉及,但DbMigrator使用了我的自定义ContextKey :)