【问题标题】:Enity Framework 6.0.0.0 : Unable to generate an explicit migration... with Code-based migration实体框架 6.0.0.0:无法生成显式迁移...使用基于代码的迁移
【发布时间】:2015-01-01 08:41:18
【问题描述】:

情况是:

  1. 每租户数据库。
  2. 基于代码的非自动迁移。 dbs 的初始创建也是通过 Code First 进行的。当前场景中没有预先存在的数据库。
  3. 在迁移脚本的生成过程中不知道确切的数据库,因为有很多。我唯一拥有的就是代码——最初基于模型的初始迁移脚本和经过一些修改的模型。
  4. 使用初始脚本生成的现有数据库 - 一切正常。这是我重现问题的方法:
  5. 运行 PS 命令:Add-Migration -Name Initial -StartUpProjectName MyApp.Web -ProjectName MyApp.Migrations -ConfigurationTypeName "MyApp.Migrations.MyMigrationConfiguration" -ConnectionString "Data Source=.\SQLEXPRESS;Database=demo-db;Trusted_Connection=假;用户 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 "Data Source=.\SQLEXPRESS;Database=demo-db;Trusted_Connection=假;用户 ID=x;密码=x" -ConnectionProviderName "System.Data.SqlClient" - Boom。
  8. 微妙 - 迁移器甚至没有连接到 MSSQL 来检查数据库是否存在或有 dbo.__MigrationHistory!我更进一步,关闭了 MSSQL 服务! - 我是否输入错误的数据库名称或关闭整个 MSSQL 服务器都没有关系 - 错误是相同的并且没有建立连接。那么,当它不检查数据库时,它如何知道迁移是挂起的呢?我假设一个错误。
  9. 我已经创建了 __dbo.MigrationHistory,其中包含初始迁移。
  10. 错误:无法生成显式迁移,因为以下显式迁移处于挂起状态:[201402121953301_Initial]。在尝试生成新的显式迁移之前应用挂起的显式迁移。

这是我的配置 - 没什么特别的:

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

这是我创建数据库的方法:

 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% 的错误,但我不知道如何解决。

【问题讨论】:

    标签: entity-framework-6


    【解决方案1】:

    我们找到了答案——我的一位聪明的同事,在Reflector.的帮助下

    1. EntityFramework.dll 里面有类
    2. System.Data.Entity.Migrations.DbMigrator 与方法
    3. Scaffold(string migrationName, string @namespace, bool ignoreChanges)
    4. 调用 this.GetPendingMigrations
    5. 哪个方法调用另一个类HistoryRepository.CreateHistoryQuery(HistoryContext context, string contextKey = null)上的另一个方法,参数contextKey == NULL
    6. 但是在这个方法里面发生了这种情况

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

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

    问题出在哪里?问题在于

    1. 我使用两个不同的 DbMigrationConfiguration 类
    2. 因为迁移程序集与应用程序的核心是分开的,这使得
    3. 它们最后是两个不同的“完全限定的命名类”
    4. 在用于生成迁移脚本的 DbMigrationConfiguration 的 dbo._MigrationHistory 表中产生两个不同的 ContextKey。

    因此,当我制作初始迁移脚本并启动站点并且站点应用该脚本时,一切正常,但在 dbo._MigrationHistory 中,ContextKey 为“MyDbConigClass1”。之后,当我尝试使用另一个 DbMigrationConfiguration 类的 Add-Migration 时,ContextKeys 不匹配 - BOOM!

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

    【讨论】:

      猜你喜欢
      • 2012-04-06
      • 1970-01-01
      • 1970-01-01
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      • 2013-12-29
      相关资源
      最近更新 更多