在迁移 Up 方法中更改数据 - Entity Framework

Change data in migration Up method - Entity Framework

我在现有模型中添加了一个新的 属性。它是一个 bool 属性,默认值为 true。此 table 中已有数据,我想在创建新字段后立即在 Up 方法中将特定行的新 属性 设置为 false。

public override void Up()
{
    AddColumn("dbo.RequestValidationErrors", "IsBreaking",
         c => c.Boolean(nullable: false));
    using (Context ctx = new Context())
    {
        var validation = 
            ctx.RequestValidationErrorSet
            .FirstOrDefault
                (x => x.WordCode == "RequestValidationError.MoreThanOneItemFound");
            if (validation != null)
            {
                validation.IsBreaking = false;
                ctx.SaveChanges();
            }
        }
    }
}

这样 EF 在说

时会抛出错误

System.InvalidOperationException: The model backing the 'DbContext' context has changed since the database was created. Consider using Code First Migrations to update the database

是否可以在此处更改数据库,还是应该在其他地方更改?

在迁移过程中,最好使用Sql()方法更新数据库数据。

Sql("UPDATE dbo.RequestValidationErrors SET IsBreaking = 0 WHERE WordCode = 'RequestValidationError.MoreThanOneItemFound'");

您还应该为新列定义默认值。所以解决方案应该是这样的:

public override void Up()
{
    AddColumn("dbo.RequestValidationErrors", "IsBreaking", c => c.Boolean(nullable: false, default: true));
    Sql("UPDATE dbo.RequestValidationErrors SET IsBreaking = 0 WHERE WordCode = \"RequestValidationError.MoreThanOneItemFound\"");
}

在迁移过程中使用 DbContext 是非常不明确的。你对上下文有什么期望?它在其模型中具有迁移后状态,但数据库在table 中具有迁移前状态。所以模型和数据库不匹配。如果您仍然坚持在代码中使用 DbContext,那么禁用模型检查可能是解决方案。您可以使用以下方法禁用模型检查:

Database.SetInitializer<Log4ProContext>(null);

更新:

从 EF Core 2.1 开始,您可以使用 UpdateData 而不是 Sql 方法来处理更简单的情况,就像@ntfrex 在回答中提到的那样:

migrationBuilder.UpdateData(
    table: "RequestValidationErrors", 
    keyColumn: "WordCode", 
    keyValue: "RequestValidationError.MoreThanOneItemFound", 
    column: "IsBreaking", 
    value: false);

我的建议是 不要对 table 使用 nameof 运算符,并且列名根本不会出现在迁移中。由于稍后重命名这些 类 会导致旧迁移在生产中失败,因为数据库中的 table 名称仍然是旧名称。

如果你想使用框架进行这样的更改,你应该将数据库更改与数据更改分开。

仅为数据库更改创建迁移,然后执行。

然后创建一个新的迁移(Up() 和 Down() 方法将为空)。您现在可以实例化您的 DatabaseContext 并且不会出现错误。这样您就可以使用框架来进行这些更改,并正确实现 Down() 方法。

为 EF6 编写 DataMigrations 可能是一件苦差事。我们整理了一个库,我只是在这里开源供其他人使用,它为 EF6 添加了这个承诺已久但缺失的功能。只需使用常规 EF 查询等编写 类

https://github.com/b9chris/Brass9.Data

除了使用 Sql 方法,您还可以使用 UpdateData 方法。

migrationBuilder.UpdateData(
    table: "RequestValidationErrors", 
    keyColumn: "WordCode", 
    keyValue: "RequestValidationError.MoreThanOneItemFound", 
    column: "IsBreaking", 
    value: false);

(不知道是不是只有ef core支持这种方式)