首页 > 解决方案 > 具有数据更改的实体框架可恢复迁移?

问题描述

如果您创建一个仅更改表结构的迁移,那么您确信您可以轻松地恢复迁移,因为它具有适用于它Up()Down()方法。

但是,如果我们有一些似乎不可恢复的数据更改怎么办?

例如,现在我有一个可以为空的列,其中包含Enum值。

Paid column
---
Paid = 0
PaidTill = 1
NotPaid = 2
(+ NULL value)

所以有4个值。现在我想将此列更改为只有 2 个值,并且此列不再可为空:

Paid column
---
NotPaid = 0
Paid = 1

因此,如果该值为 NULL 它将是NotPaid,PaidTill成为Paid等等。

我知道我可以Up()使用数据操作 SQL 扩展方法,但是这种迁移可以恢复吗?

标签: c#.netsql-serverentity-frameworkentity-framework-6

解决方案


您描述的数据操作显然会丢失数据。除非您可以根据系统中的其他数据扣除原始值,否则无法还原它。

如果您没有其他数据,您可以将其创建为迁移的一部分。备份方法中的原始值Up(复制到单独的列/表/模式/数据库)。在该Down方法中,从备份中读取原始值,并删除备份:

protected override void Up(MigrationBuilder migrationBuilder)
{
    // before any manipulations:
    // create a backup table and copy data from the original column
    // assuming MyId is the primary key in the original table

    migrationBuilder.Sql(@"
        SELECT *
        INTO MyNewBackupTable
        FROM (SELECT MyId, MyNullableColumn FROM MyOriginalTable)
    "); 

    // ... perform the desired manipulations 
}

protected override void Down(MigrationBuilder migrationBuilder)
{
    // ... revert other manipulations,
    // (including making the column nullable again)

    // update the column from the data in the backup table
    migrationBuilder.Sql(@"
        UPDATE MyOriginalTable
        SET t1.MyNullableColumn = t2.MyNullableColumn
        FROM MyOriginalTable AS t1
        INNER JOIN MyNewBackupTable AS t2
        ON t1.MyId = t2.MyId 
    ");

    // remove the backup table
    migrationBuilder.Sql(@"DROP TABLE MyNewBackupTable");
}

Up如果要求允许您定义“不归路点”,您还可以在后续迁移之一 ( ) 中删除备份。


推荐阅读