【问题标题】:Selectively Disabling Cascade Delete on Many-to-Many Link Table在多对多链接表上选择性禁用级联删除
【发布时间】:2023-04-09 22:50:01
【问题描述】:

是否可以选择性地删除 Entity Framework 5 Code First 中自动生成的多对多链接表上的级联删除选项?这是一个需要它的简单示例:

public class Parent
{
    public int Id { get; set; }

    public virtual IList<ChildA> As { get; set; }
    public virtual IList<ChildB> Bs { get; set; }
}

public class ChildA
{
    public int Id { get; set; }
    [Required]
    public virtual Parent Parent { get; set; }

    public virtual IList<ChildB> ChildBJoins { get; set; }
}

public class ChildB
{
    public int Id { get; set; }
    [Required]
    public virtual Parent Parent { get; set; }

    public virtual IList<ChildA> ChildAJoins { get; set; }
}

public class TestContext : DbContext
{
    public DbSet<Parent> Parents { get; set; }
    public DbSet<ChildA> As { get; set; }
    public DbSet<ChildB> Bs { get; set; }
}

由于链接表上引入了级联删除选项,当前形式的此上下文将不适用于数据库。如果我要创建手动链接表,我可以使用 Fluent API 将其一侧配置为不级联,但该选项在多对多关系中不可用。

我知道我可以通过删除 ManyToManyCascadeDeleteConvention 按照this question 禁用所有多对多连接上的级联删除,但这不是我所追求的 - 我只是希望能够做到它适用于一种关系,或者理想情况下是一种关系的一侧。

【问题讨论】:

  • 您可能必须在Parent-ChildAParent-ChildB 一对多关系上禁用级联删除才能解决问题。
  • 我不想那样做——我想把这种关系留在那里,从多对多中删除。如果我创建一个手动链接实体,我可以做到这一点,但找不到自动链接实体的方法。

标签: entity-framework ef-code-first entity-framework-5


【解决方案1】:

我怀疑在 EntityTypeConfiguration 映射类中没有办法做到这一点,但我通过更改 DbMigration 类的 Up() 方法中的代码来做到这一点。

为链接表生成的代码是:

CreateTable(
    "dbo.ChildBChildAs",
    c => new
        {
            ChildB_Id = c.Int(nullable: false),
            ChildA_Id = c.Int(nullable: false),
        })
    .PrimaryKey(t => new { t.ChildB_Id, t.ChildA_Id })
    .ForeignKey("dbo.ChildBs", t => t.ChildB_Id, cascadeDelete: true)
    .ForeignKey("dbo.ChildAs", t => t.ChildA_Id, cascadeDelete: true)
    .Index(t => t.ChildB_Id)
    .Index(t => t.ChildA_Id);

您应该能够通过将不想级联的一侧更改为 false 来使其工作:

    .ForeignKey("dbo.ChildAs", t => t.ChildA_Id, cascadeDelete: false)

如果您可以像使用一对多一样使用 FluentAPI 来做到这一点,那就太好了,但是我还没有找到方法来做到这一点

【讨论】:

  • 这不是最佳解决方案,因为可能需要重新构建迁移,在这种情况下您会丢失所做的编辑。在 EF 6 中,您可以禁用该约定,但这会为所有与 modelBuilder.Conventions.Remove&lt;ManyToManyCascadeDeleteConvention&gt;() 的多对多关系关闭它,但这也可能是不希望的。
  • @FRoZeN 完全禁用约定当然不会有选择性地禁用它。也许最好的解决方案是创建一个手动链接实体,正如理查德在他的评论中发布的那样,但如果您知道更好的方法,如果您发布它会很棒
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-15
  • 2013-01-13
相关资源
最近更新 更多