【问题标题】:EF Core - How do I add a non-nullable foreign key property?EF Core - 如何添加不可为空的外键属性?
【发布时间】:2019-11-26 14:10:47
【问题描述】:

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

我有一个Donation 类...

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

到目前为止,所有捐款均假定为英镑。我们想要添加对其他货币的支持,因此想要添加一个Currency 类(最终将作为Currencies 表),并有一个从DonationCurrency 的外键链接。我将以下代码添加到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 = "$" },
    //...
  });

但是,这在更新数据库时出错,因为它试图将 CurrencyID 的值设置为 null。

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

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

澄清一下,CurrencyID 属性应该是不可为空的,因为每次捐赠都必须使用某种货币。

如何使用 EF Core 迁移执行此操作?

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

【问题讨论】:

  • 将您的货币添加为迁移的一部分是否适合您?在DbContext.OnModelCreating 上使用HasData?或者,或者,在迁移中手动添加插入语句。
  • @ESG 我已经在使用HasData 添加数据(请参阅我更新的问题),但似乎添加的不够早。请你能解释更多关于添加插入语句的信息,因为我对 EF Core 的经验不够(还)知道如何做到这一点。谢谢

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


【解决方案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);

【讨论】:

    【解决方案2】:

    有几种不同的方法可以解决它。

    1)

    • 使用不可为空的属性生成迁移,并像现在一样包含数据,但修改迁移以将列添加为可空,并预填充数据并稍后将其更改为不可空可以为空。

    2)

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

    【讨论】:

    • 谢谢,但正如我在问题中指出的那样,我试过了,但仍然出现错误。从我在您之前发布的答案中可以看出,主要问题是我忘记为 CurrencyID 属性设置默认值。一旦我这样做了,并解决了级联删除问题,一切正常。还是谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 2017-02-15
    • 2015-06-03
    • 2021-11-10
    • 1970-01-01
    相关资源
    最近更新 更多