数据库在更新时应用所有以前的迁移,而不仅仅是新的迁移

Posted

技术标签:

【中文标题】数据库在更新时应用所有以前的迁移,而不仅仅是新的迁移【英文标题】:Database applies ALL previous migrations on update and NOT just the new one 【发布时间】:2016-07-27 06:36:16 【问题描述】:

我正在开发一个网站,目前该网站既有生产数据库,也有测试数据库。 生产数据库托管在外部,而测试数据库托管在本地。

每当我对数据库进行更改时,我都会通过迁移应用更改。 添加新迁移后,我在生产和测试数据库上运行 update-database 命令以保持它们同步。

我将迁移很好地应用于我的生产数据库,但是,当我想将迁移应用于我的测试数据库时,我看到它尝试应用所有以前的迁移(而不仅仅是新的迁移):

这是输出:

应用显式迁移:[201603230047093_Initial, 201603232305269_AddedBlobNameToImage, 201603242121190_RemovedSourceFromRealestateDbTable, 201603311617077_AddedSourceUrlId, 201604012033331_AddedIndexProfileAndFacebookNotifications, 201604012233271_RemovedTenantIndexProfile, 201604042359214_AddRealestateFilter]。应用显式迁移: 201603230047093_Initial。 System.Data.SqlClient.SqlException (0x80131904): 已经有一个名为“城市”的对象 数据库。

显然它失败了,因为数据库的当前状态是第二次最新迁移。但是我想知道为什么它会尝试应用所有以前的迁移?

与生产数据库(一次应用了所有迁移)不同,测试数据库在上一次迁移中被删除并创建,因此其迁移历史表仅包含一行:

201604012239054_InitialCreate 

(我假设 InitialCreate 是所有先前迁移组合的自动生成的名称)。

总结:

为什么测试数据库会尝试应用所有以前的迁移,而不仅仅是新添加的迁移?

编辑: 运行 COMMMAND 时,我得到以下输出脚本:

DECLARE @CurrentMigration [nvarchar](max)

IF object_id('[dbo].[__MigrationHistory]') IS NOT NULL
    SELECT @CurrentMigration =
        (SELECT TOP (1) 
        [Project1].[MigrationId] AS [MigrationId]
        FROM ( SELECT 
        [Extent1].[MigrationId] AS [MigrationId]
        FROM [dbo].[__MigrationHistory] AS [Extent1]
        WHERE [Extent1].[ContextKey] = N'Boligside.Migrations.Configuration'
        )  AS [Project1]
        ORDER BY [Project1].[MigrationId] DESC)

IF @CurrentMigration IS NULL
    SET @CurrentMigration = '0'

IF @CurrentMigration < '201603230047093_Initial'

(它继续为每个先前的迁移制作 if 语句)

我的数据库中的当前迁移表如下所示(请注意,第一行用于日志框架,因此不相关):

【问题讨论】:

试试这个调试:生成一个完整的脚本 update-database -Script –SourceMigration $InitialDatabase。现在检查您的测试数据库的 __MigrationHistory 表,并确保 MigrationId 和 ContextKey 与脚本为每次迁移检查的内容相匹配。如果这对您没有帮助,我可以给您一个解决方法。 @SteveGreene 我已经生成了脚本,我看到 ContextKey 是“N'Boligside.Migrations.Configuration”,它与数据库中行的 ContextKey 名称“RealestateSiteModel”不匹配.RealestateSiteDbContext”。我还用脚本输出更新了我的问题。请让我知道您对此的看法。 由于 PROD 正在工作,只需更改 TEST 中存在的迁移的上下文键以匹配。您也可以只注释掉已经运行的迁移的 Up() 代码,但如果您愿意,这将在 __MigrationHistory 中插入更多记录。 @SteveGreene 我在测试和生产中使用相同的 dbcontext,并在两者之间切换时简单地交换连接字符串。 “更改迁移的上下文键”是什么意思? 在数据库表中。 EF 检查 __MigrationHistory 以查看已运行的内容。 【参考方案1】:

可能导致迁移重新运行的一个问题是,您的上下文键是否在重构期间发生更改。有几种方法可以解决这个问题:

1) 用新值更新 __MigrationHistory 中的旧记录:

UPDATE [dbo].[__MigrationHistory]
   SET [ContextKey] = ‘New_Namespace.Migrations.Configuration’
 WHERE [ContextKey] = ‘Old_Namespace.Migrations.Configuration’

2) 您可以将旧的上下文键硬编码到迁移配置类的构造函数中:

public Configuration()

    AutomaticMigrationsEnabled = false;
    this.ContextKey = “Old_Namespace.Migrations.Configuration”;

这是一篇关于迁移如何在后台运行的好文章:https://msdn.microsoft.com/en-US/data/dn481501?f=255&MSPPError=-2147217396

另见http://jameschambers.com/2014/02/changing-the-namespace-with-entity-framework-6-0-code-first-databases/

【讨论】:

绝对漂亮:-)

以上是关于数据库在更新时应用所有以前的迁移,而不仅仅是新的迁移的主要内容,如果未能解决你的问题,请参考以下文章

即使 url 是新的,浏览器也不会下载更新的 css、js 等

反应渲染正在使用新旧状态值,而不仅仅是新值

强制核心数据更新模型

循环中的 PL/SQL 异常

如何删除种子而不会对数据库产生任何影响?

轻量级数据迁移