EF Core-如何添加不可为空的外键属性?

时间:2019-07-17 17:05:40

标签: entity-framework asp.net-core ef-migrations

VS2019中的ASP.NET ASP Core 2.2和EF。

我有一个Donation课...

public class Donation {
  public int Id { get; set; }
  // other properties...
}

到目前为止,所有捐款均假定为英镑。我们要添加对其他货币的支持,因此要添加Currency类(最终将作为Currencies表),并具有从Donation到{ {1}}。我将以下代码添加到Currency ...

Donation

...以及以下课程...

  public int CurrencyID { get; set; }

  [ForeignKey(nameof(CurrencyID))]
  public virtual Currency Currency { get; set; }

我还填充了public class Currency { public int Id { get; set; } public string Code { get; set; } public string Symbol { get; set; } public virtual IEnumerable<Donation> Donations { get; set; } } 表...

Currencies

但是,这在更新数据库时出现了错误,因为它试图将 builder.Entity<Currency>().HasData(new List<Currency> { new Currency { Id = (int)SupportedCurrencies.GBP, Code="GBP", Symbol = "£" }, new Currency { Id = (int)SupportedCurrencies.EUR, Code="EUR", Symbol = "€" }, new Currency { Id = (int)SupportedCurrencies.USD, Code="USD", Symbol = "$" }, //... }); 的值设置为null。

我尝试添加两次迁移,一次迁移具有可为空的CurrencyID属性,第二次迁移为非空,希望数据库更新可以运行代码以在两者之间填充CurrencyID表,但这也不起作用。关于无法将Currencies属性的值设置为null,因为它不可为空,我也遇到了同样的错误。

Pre-Core,我将添加一个CurrencyID表,然后在SQL脚本中填充它,然后将该列添加到Currencies表中,并将Donations属性设置为是所有现有捐款的英镑ID。

为澄清起见,CurrencyID属性应不可为空,因为每次捐赠都必须使用某种货币。

如何通过EF Core迁移做到这一点?

几年前有人问the same question,但没有得到答案。

2 个答案:

答案 0 :(得分:1)

原来我错过了为CurrencyID属性设置默认值的过程。现在我有点明显了。

我添加了以下内容...

  builder.Entity<Donation>()
    .Property(p => p.CurrencyID)
    .HasDefaultValue(1);

...错误消失了。

另一方面,这给了我关于引起循环或多个级联路径的不同错误。通过在迁移中修改Up方法,将onDelete设置为Restrict而不是默认的Default ...

,可以解决此问题
        migrationBuilder.AddForeignKey(
            name: "FK_Donations_Currencies_CurrencyID",
            table: "Donations",
            column: "CurrencyID",
            principalTable: "Currencies",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);

答案 1 :(得分:0)

有几种解决方法。

1)

  • 使用不可为空的属性(包括现在的数据)来生成迁移,但是请修改迁移,以便将列添加为可为空,并预先填充数据并稍后对其进行更改以使其变为不可可为空。

2)

  • 生成一个属性为可空的迁移,并包括现在的数据
  • 使该属性不可为空,并生成第二个迁移,但是在顶部,通过SQL手动进行更新。