【问题标题】:Seed script in Entity Framework Core is breaking my migrationEntity Framework Core 中的种子脚本正在破坏我的迁移
【发布时间】:2021-04-19 11:30:33
【问题描述】:

我有一个非常简单的场景,其中我有许多相关实体,其中一些预计会被预填充(通过种子脚本)。然后,我运行我的应用程序,它添加了一个新的相关数据(与种子脚本填充的表相关)。

最终,当我想添加一个新的迁移时,例如使一个字段可以为空(一个未播种的实体),我尝试了 update-database 命令并且一切都崩溃了,因为迁移试图重新创建我的种子表。这是不可能的,因为他们保留了外键。

我会更具体:

汽车(ID、品牌、颜色、年份)

多对一

CarType(ID、值)

所以,在我的 DbContext 中,我有以下内容:

modelBuilder.Entity<CarType>()
                .HasData(new CarType('4125ad9e-68fe-4d25-9d73-7e8acc097d6f', 'Coupe'))

然后,我运行我的应用程序并开始插入具有相应类型的新 Cars。所以,现在我有:

Car(1, 'BMW', 'Black', 2011) FK-> CarType('4125ad9e-68fe-4d25-9d73-7e8acc097d6f', 'Coupe')
Car(2, 'Audi', 'Green', 2008) FK-> CarType('cc097d6f9e-68fe-4d25-9d73-4125ad7e8a', 'Estate')

但是,有一天我决定让Year 字段可以为空

public int? Year { get; set; }

我跑了add-migration,一切看起来都很好,除了Up语句中的那个:

migrationBuilder.DeleteData(
                table: "CarType",
                keyColumn: "Id",
                keyValue: new Guid("4125ad9e-68fe-4d25-9d73-7e8acc097d6f"));

一旦我执行update-database,我就会收到一个错误,指出该操作无法执行,因为有一个与我要删除的实体相关的外键:

DELETE 语句与 REFERENCE 约束冲突

我应该如何处理?我的种子票现在有点挡住我了。我希望能够对我的其他表进行更改,即使是在不需要重新创建内容的情况下使用种子脚本编写的表。

【问题讨论】:

  • @GertArnold 已更正。谢谢。

标签: c# entity-framework-core


【解决方案1】:

我认为您在 DB 中的记录取决于 Card Type Id 与您尝试删除的相同 Id 因此您可以手动从数据库中删除所有依赖实体,然后应用更新数据库,这不推荐 要么 在 onModelCreating 函数中将所有与 CardType 有关系的实体更改为“级联”

例子

entity.HasOne(d => d.CardTypes)
                .WithMany(p => p.Cards)
                .HasForeignKey(d => d.CardTypeId)
                .OnDelete(DeleteBehavior.Cascade)   /* Cascade */
                .HasConstraintName("FK_Cards_CardTypes");

【讨论】:

  • 我不想在应用迁移时删除 Cars。
  • 您应该删除所有依赖于您尝试删除的卡类型的实体,因为这些实体之间存在关系,因为迁移尝试删除卡类型但违反了约束
  • 是否必须删除我没有更改的实体?难道不能以某种方式配置迁移,所以它不考虑这些吗?
  • 如果您的 CardType 表中仍有 ID 为“4125ad9e-68fe-4d25-9d73-7e8acc097d6f”的卡类型,那么您应该删除此记录以及取决于它的内容,如果不只是评论 DeleteData 行会工作的
  • 这就是我现在正在做的,但我不确定它的一致性如何。我试图为此找到某种自动化。
【解决方案2】:

我的解决方案是从我的 DbContext 中删除与 HasData 相关的种子,因为当添加迁移时,对使用 HasData 指定的数据的更改会转换为调用InsertData()、UpdateData() 和 DeleteData()。

所以,正如HERE 的建议,我将初始化逻辑移到了我的初始迁移中。

migrationBuilder.InsertData(
    table: "CarType",
    columns: new[] { "Id", "Value" },
    values: new object[] { "4125ad9e-68fe-4d25-9d73-7e8acc097d6f", "Coupe" });

【讨论】:

    猜你喜欢
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 2017-05-16
    • 2017-10-27
    • 1970-01-01
    • 2018-11-05
    • 2020-03-09
    • 2017-02-06
    相关资源
    最近更新 更多