【问题标题】:Disable cascade delete on EF Core 2 globally全局禁用 EF Core 2 上的级联删除
【发布时间】:2018-03-13 13:36:21
【问题描述】:

我需要了解在EF Core 2 中全局禁用级联删除的方法。任何帮助都可以得到。

在 EF 6.x 中,我们使用以下代码禁用 OneToManyManyToMany 的级联删除:

builder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
builder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

【问题讨论】:

标签: entity-framework entity-framework-core


【解决方案1】:

不幸的是,目前的 EF Core(目前是最新的 v2.0)没有公开一种全局控制约定的好方法。

默认的 EF Core 2.0 约定是使用 DeleteBehavior.Cascade 表示必需关系,使用 DeleteBehavior.ClientSetNull 表示可选关系。我可以建议的解决方法是在OnModelCreating 覆盖末尾的典型元数据模型循环。在这种情况下,定位所有已经发现的关系并相应地修改它们:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // ...

    var cascadeFKs = modelBuilder.Model.GetEntityTypes()
        .SelectMany(t => t.GetForeignKeys())
        .Where(fk => !fk.IsOwnership && fk.DeleteBehavior == DeleteBehavior.Cascade);

    foreach (var fk in cascadeFKs)
        fk.DeleteBehavior = DeleteBehavior.Restrict;

    base.OnModelCreating(modelBuilder);
}

【讨论】:

  • 感谢您的回答。 cascadeFKs 这里只包含“一对多”关系还是也包含“多对多”关系?
  • 目前 EFC 中没有特殊的many-to-many 关系(它们用 2 one-to-many 模拟)。所以要回答你的问题,cascadeFks 包含所有关系 - one-to-manyone-to-one
  • @AuthorProxy EF Core 中没有 onUpdateBehavior。唯一的更新选项是DeleteBehavior.SetNull。您可以在stackoverflow.com/questions/48521939/… 处查看当前的 EFC 选项及其关系映射。如果您尝试对可变 PK 建模,则根本不支持。
  • @IvanStoev 根据the current documentation,所需关系的默认行为是Cascade
  • @MattJenkins 我相信!fk.IsOwnership 也是如此
【解决方案2】:
constraints: table =>
                {
                    table.PrimaryKey("PK_ComandaPlato", x => x.ComandaPlatoId);
                    table.ForeignKey(
                        name: "FK_ComandaPlato_Comanda_ComandaId",
                        column: x => x.ComandaId,
                        principalTable: "Comanda",
                        principalColumn: "ComandaId",
                        onDelete: ReferentialAction.Cascade);//default: cascade on
                    table.ForeignKey(
                        name: "FK_ComandaPlato_Plato_PlatoId",
                        column: x => x.PlatoId,
                        principalTable: "Plato",
                        principalColumn: "PlatoId",
                        onDelete: ReferentialAction.NoAction);//turn off cascade,"by hand"
                });
//comments: modifing the auto-generated migration, "harcode by hand" this attibute, as view bellow: change "Cascade" to "NoAction" (as view 1st and 2st examples)

【讨论】:

    【解决方案3】:

    可能会有所帮助:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
    ChangeTracker.CascadeDeleteTiming = ChangeTracking.CascadeTiming.Never;
    ChangeTracker.DeleteOrphansTiming = ChangeTracking.CascadeTiming.Never;
    }
    

    【讨论】:

    • 也许,也许不是。你能不能说得更有说服力?提示:在将其作为答案发布之前对其进行测试。
    • 你甚至不被允许这样做。你得到:InvalidOperationException: An attempt was made to use the context while it is being configured. A DbContext instance cannot be used inside OnConfiguring since it is still being configured at this point
    猜你喜欢
    • 1970-01-01
    • 2018-07-19
    • 1970-01-01
    • 2018-08-19
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多