【问题标题】:Entity Framework code-first migrations does not generate a foreign key and ignores the ForeignKey data annotation实体框架代码优先迁移不生成外键并忽略 ForeignKey 数据注释
【发布时间】:2020-07-30 20:48:45
【问题描述】:

我正在尝试使用 EF 代码优先迁移向我的数据库表添加外键,但是当我运行 add-migration 时,生成的迁移中的 Up()Down() 方法为空。

外键应该链接到的基表是Reservation,而我要添加键的表是Batch

预留模型类:

public class Reservation
{
    [Key]
    public int ReservationId { get; set; }

    public virtual ICollection<Batch> Batches { get; set; }
    
    ...
}

Batch模型类:

public class Batch
{
   [Key]
   public int BatchId { get; set; }
   
   public int ReservationId { get; set; }

   [ForeignKey("ReservationId")]
   public Reservation Reservation { get; set; }

   ...
}

Reservation 属性以前称为 TempReservation,并且没有 [ForeignKey] 注释,这就是为什么一开始没有创建外键的原因。

我尝试通过添加[ForeignKey] 注释并将属性名称更改为Reservation 来修复它,就像上面的代码 sn-p 显示的那样,但无济于事。

迁移总是忽略我的更改,给我空Up()Down()

我还有其他遵循相同“结构”的模型类,它们都有外键,没有任何问题。唯一的区别是我在 Batch 表已经创建之后添加这个 FK。

【问题讨论】:

  • 您显示的代码并不表示有任何问题。
  • 更新:我仍然无法让它生成应有的迁移,谁知道为什么,但我能够通过手动添加 AddForeignKey("dbo.Batches", "ReservationId", "dbo.Reservations", "ReservationId", cascadeDelete: true); 到迁移来添加外键。

标签: c# entity-framework entity-framework-6 ef-code-first entity-framework-migrations


【解决方案1】:

如果您从头开始,您的代码模型设置应该可以工作,因此您的模型看起来没问题。问题是由于第一次不使用[ForeignKey] 属性,您的数据库模式现在可能有一个额外的Shadow Property 列,称为Reservation_ReservationId。但是,由于此字段不是模型中的活动声明,因此很难直接定位,因为您的约定配置会极大地影响这一点,例如,如果您配置了适当的约定,shadow 属性 可能已经被命名为ReservationId

尝试通过添加 [ForeignKey] 注释并将属性名称更改为 Reservation 来修复它,如上面代码 sn-p 所示,但无济于事。

如上所述,数据库可能已经根据public virtual ICollection&lt;Batch&gt; Batches { get; set; }在数据库中生成了正确的外键。

要记住的事情:

  • 每当对模型进行更改以重命名字段和/或修改现有字段的索引或关系时,您必须在单独迁移中执行这些操作,否则迁移生成逻辑无法理解您将不得不手动应用更改。

    • 如果您一次性完成这些操作,您几乎总是需要以某种方式手动编辑迁移文件。
  • 应用您手动修改的迁移逻辑到数据库后,如果您现在运行add-migration 命令,它应该会生成一个空迁移。如果是这种情况,那么您通常可以继续前进。

相反,您可以遵循以下流程:

  1. 重命名导航属性和任何其他字段。
  2. Add-Migration...查看生成的输出
  3. '更新数据库`...
  4. 添加ForeignKey 属性
  5. Add-Migration...查看输出,如果为空,请检查外键是否尚未在数据库中正确定义
  6. 'Update-Database`... 如有必要

Code First 迁移并非完美的开箱即用

它仍然是一个非常有用的工具,但您需要查看生成的代码并根据需要添加。扩展它以支持默认值声明或任何 SQL DDL 管理查询并不难。

【讨论】:

    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多