将新的必填字段添加到具有 EF 代码优先迁移的表之一

本文关键字:迁移 代码 EF 字段 添加 | 更新日期: 2023-09-27 18:33:01

我正在使用EF Code First Migration。我已经有很多关于生产 Db 的数据,我想引入一个不可为空的字段。怎么可能?

当前它抛出一个错误:

The column cannot contain null values. [ Column name = Test,Table name = 'MyTable'] 

将新的必填字段添加到具有 EF 代码优先迁移的表之一

我通常为此使用的策略是首先将新列作为可选列引入,填充它,然后将其设置为必需列。实际上,您可以通过为每个步骤进行单独的迁移来执行单独的迁移步骤,或者手动更改自动生成的迁移代码以使更改全部发生在一次迁移中。我将介绍如何使用单个迁移。

如果添加新的[Required]字段,自动生成的迁移可能如下所示,如果dbo.MyTable其中包含数据,则会失败:

public override void Up()
{            
    AddColumn("dbo.MyTable", "MyColumn", c => c.String(nullable: false));
}
    
public override void Down()
{
    DropColumn("dbo.MyTable", "MyColumn");
}

您可以编辑迁移以最初将列添加为可选列,预填充它,然后将其标记为必需。您可以使用Sql()来执行预填充。根据您的数据,您可能希望根据其他列甚至另一个表计算新列的值,您可以通过编写适当的 SQL 来做到这一点。

public override void Up()
{
    AddColumn("dbo.MyTable", "MyColumn", c => c.String());
    Sql("UPDATE dbo.MyTable SET MyColumn = COALESCE(SomeOtherColumn, 'My Fallback Value')");
    AlterColumn("dbo.MyTable", "MyColumn", c => c.String(nullable: false));
}
    
public override void Down()
{
    DropColumn("dbo.MyTable", "MyColumn");
}

如果只想在所有行上设置相同的值,则可以跳过Sql()步骤,并根据需要添加列,并在删除defaultValue之前使用defaultValue。这允许您在迁移期间将所有行设置为相同的值,同时仍要求您在添加新行时手动指定该值。这种方法应该不适用于旧版本的 EF。我不确定需要哪个版本的 EF,但它至少应该适用于现代版本(≥6.2(:

public override void Up()
{
    AddColumn("dbo.MyTable", "MyColumn", c => c.String(defaultValue: "Some Value", nullable: false));
}
    
public override void Down()
{
    DropColumn("dbo.MyTable", "MyColumn");
}

您可以在迁移文件中添加一个默认值,如下所示:

    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<string>(
            name: "MyColumn",
            table: "dbo.MyTable",
            nullable: false,
            defaultValue: "");
    }

如果列是布尔值,那么您只需根据需要输入默认值 false 或 true。

在 EFCore 3.1 中,您只需添加必需的属性,它就会自动设置默认值

布尔值默认为 false

[Required]
public Boolean myField {get;set;}

整数默认值为 0

[Required]
public int myField {get;set;}

字符串默认为 ">

[Required]
public string myField {get;set;}