在迁移中更改数据Up方法-实体框架

本文关键字:方法 实体 框架 Up 数据 迁移 | 更新日期: 2023-09-27 18:20:37

我在现有模型中添加了一个新属性。它是一个bool属性,默认值为true。这个表中有现有的数据,我想在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:支持自创建数据库以来,"DbContext"上下文已更改。考虑使用代码优先迁移来更新数据库

可以在这里更改数据库吗?还是应该在其他地方更改?

在迁移中更改数据Up方法-实体框架

在迁移过程中,最好使用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是非常模糊的。你期望从上下文中得到什么?它的模型中有迁移后状态,但数据库的表中有迁移前状态

Database.SetInitializer<Log4ProContext>(null);

更新:

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

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

我的建议是在迁移中根本不要将nameof运算符用于表和列名。因为以后重命名这些类会导致旧的迁移在生产中失败,因为数据库中的表名仍然使用旧名称。

不使用Sql方法,也可以使用UpdateData方法。

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

(我不知道是否只有ef核心支持这种方法)

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

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

然后创建一个新的迁移(Up()和Down()方法将为空)。您现在可以实例化您的DatabaseContext,并且不会出现任何错误。通过这种方式,您可以使用Framework进行这些更改,并正确地实现Down()方法。

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

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