【问题标题】:MigrateDatabaseToLatestVersion not executed未执行 MigrateDatabaseToLatestVersion
【发布时间】:2013-09-04 04:37:44
【问题描述】:

我无法弄清楚为什么我的最新迁移没有在应用程序启动时自动执行(或至少在首次访问数据库上下文时)。我曾经在开发中手动运行 update-database,但我想测试它是否会在我托管的测试环境中自动升级。

在 Application_Start() 中:

Database.SetInitializer<FepazoContext>(
    new MigrateDatabaseToLatestVersion<FepazoContext, FepazoConfiguration>())

在 FepazoConfiguration 中:

internal sealed class FepazoConfiguration : 
    DbMigrationsConfiguration<Fepazo.Models.FepazoContext>
{
    public FepazoConfiguration()
    {
        AutomaticMigrationsEnabled = true;
    }
}

我什至在 FepazoContext 的构造函数中添加了这个:

public FepazoContext() : base("DefaultConnection")
{
    Database.Initialize(false);
}

一些额外的信息:

  • 迁移是通过 add-migration 自动创建的,看起来还不错。
  • 当我查询__MigrationHistory 表时,我可以看到迁移尚未“记录”为已执行。
  • 我验证了 Web.config 文件中的初始化程序或 AutomaticMigrationsEnabled 设置没有被覆盖。
  • FepazoContext 构造函数和FepazoConfiguration 中的断点受到攻击。

我是不是忘记了什么?我可以深入挖掘以找出问题所在吗?

更新

True 传递给Database.Initialize 以尝试强制迁移也无效。 Database.CompatibleWithModel(true) 返回 false - 因此系统检测到存在差异,但它不执行挂起的迁移!

public FepazoContext() : base("DefaultConnection")
{
    if (!Database.CompatibleWithModel(true))
    {
        // This is executed (each time the code enters)
        Database.Initialize(true);
    }
}

解决方法

作为一种解决方法,我在设置初始化程序后立即显式调用DbMigrator.Update()。这就是诀窍,虽然我仍然想知道为什么它不能自动工作......

protected void Application_Start()
{
    // <...>
    Database.SetInitializer<FepazoContext>(
        new MigrateDatabaseToLatestVersion<FepazoContext, FepazoConfiguration>());
    var dbMigrator = new DbMigrator(new FepazoConfiguration());
    dbMigrator.Update();
    // <...>
}

【问题讨论】:

    标签: asp.net-mvc entity-framework ef-code-first database-migration


    【解决方案1】:

    确保 MigrateDatabaseToLatestVersion 将使用应用程序正在使用的正确上下文。这是通过使用参数 useSuppiedContext 完成的。

    Database.SetInitializer<FepazoContext>(
        new MigrateDatabaseToLatestVersion<FepazoContext, FepazoConfiguration>(useSuppliedContext: true));
    

    在此更改之后,我的 MVC 应用程序确实更新了我的数据库。

    【讨论】:

      【解决方案2】:

      我遇到了这个问题。我的问题原来是我有一个 MigrationsContextFactory 用于提供连接字符串。当数据库初始化发生时,迁移上下文工厂被调用。此 MigrationsContextFactory 正在获取到另一个数据库的连接字符串,并确保它是最新的。

      我删除了 MigrationsContextFactory 并将 true 传递给 MigrateDatabaseToLatestVersion&lt;,&gt; Migrator 以告诉它使用当前上下文。看到这个问题顶票答案How do I inject a connection string into an instance of IDbContextFactory<T>?

      【讨论】:

      • 我假设由于IDatabaseInitializer&lt;TContext&gt;.InitializeDatabase(TContext) 接受了TContext 参数,它总是会使用提供的上下文。所有其他的内置初始化程序甚至都没有这个选项,所以奇怪的是他们给它的行为与框架的其余部分不一致。 (抱歉吐槽)。
      【解决方案3】:

      根据another answer on here,初始化程序在与数据库进行一些交互之前不会运行。答案解释了如何强制初始化程序立即运行。

      【讨论】:

      • 当然,这就是为什么我在第一句话中添加了“(或至少在第一次访问数据库上下文时)”,以及为什么我说我尝试了Database.Initialize(true); 没有效果。不幸的是,这个问题的解决方案并不是那么简单;)
      • 哇,我花了 15 分钟研究这个问题,因为我正在启动我的应用程序但没有登录(/与应用程序交互),实际上它必须与数据库交互才能执行迁移:')
      【解决方案4】:

      在上面的代码 sn-p 中,您在创建上下文实例后立即调用 Database.Initialize() 方法。在这种情况下,数据库将在调用 Initialize() 方法后立即创建,而不是等到第一次使用上下文。

      Initialize() 方法采用一个布尔参数,该参数控制初始化过程是否应该重新运行,如果它已经为应用程序运行。

      指定 false 将跳过已经执行的初始化过程。 true 值将再次初始化数据库,即使它已经初始化。

      【讨论】:

      • 感谢您的回答。这并不能解释为什么系统没有检测到它必须使用最新的迁移来更新数据库。我尝试将true 作为参数传递给Database.Initialize() 以强制升级,但即使这样也不会执行。
      猜你喜欢
      • 2015-07-18
      • 2018-02-14
      • 2016-07-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-14
      • 2014-05-11
      • 2012-06-28
      • 2014-01-07
      相关资源
      最近更新 更多