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

Per*_*ier 42 c# asp.net-mvc entity-framework ef-migrations

我在现有模型中添加了一个新属性.它是一个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();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

这样,EF在说话时会抛出错误

System.InvalidOperationException:自创建数据库以来,支持'DbContext'上下文的模型已更改.考虑使用Code First Migrations来更新数据库

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

meh*_*dvd 51

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

Sql("UPDATE dbo.RequestValidationErrors SET IsBreaking = 0 WHERE WordCode = 'RequestValidationError.MoreThanOneItemFound'");
Run Code Online (Sandbox Code Playgroud)

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

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\"");
}
Run Code Online (Sandbox Code Playgroud)

DbContext在它的中间使用a 是非常模糊的.您对上下文的期望是什么?它在模型中具有迁移后状态,但数据库在表中具有迁移前状态.所以模型和数据库不匹配.如果您仍坚持在DbContext代码中使用,则禁用模型检查可能是解决方案.您可以使用以下方法禁用模型检

Database.SetInitializer<Log4ProContext>(null);
Run Code Online (Sandbox Code Playgroud)

  • 感谢您提供解决方案以及缺少的defaultValue. (2认同)
  • 当你找到你要找的东西并由你的朋友回答时,感觉非常好:) (2认同)

use*_*386 17

如果要将框架用于此类更改,则应将数据库更改与数据更改分开.

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

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

  • 这个“解决方案”非常危险,因为它一开始看起来很有效,但事实并非如此。一旦您创建另一个更改数据库模型的迁移,它就不再起作用,因为这样您就无法创建数据库上下文,因为模型不再是数据库 (5认同)

NtF*_*reX 9

Sql您也可以使用该UpdateData方法,而不是使用该方法.

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

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

  • 我是 EF Core 的新手,但我认为使用 nameof 不是一个好主意。每个迁移只是关于如何根据数据库当前状态更新(或降级)模式的描述。这可以递归应用,以便升级多个架构版本。在迁移中使用 nameof 会将迁移逻辑与代码状态耦合起来,因此可能会失败,因为属性名称的更改现在会影响所有过去使用 nameof(property) 的迁移逻辑。 (11认同)
  • EF Core 从 v2.1 开始支持此功能 (2认同)