在实体框架 7 中指定“删除时不执行任何操作”

本文关键字:执行 任何 操作 删除 框架 实体 | 更新日期: 2023-09-27 18:30:12

在实体框架 7 中,当我尝试应用迁移时,出现错误

在表"ChangeOrder"上引入外键约束"FK_ChangeOrder_User_CreatedByID"可能会导致循环或多个级联路径。指定"删除时不执行任何操作"或"更新时不执行任何操作",或修改其他外键约束。
无法创建约束。请参阅以前的错误。

我知道在旧版本的实体框架中,您可以通过添加

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

到 DbContext,但在 EF7 中,modelBuilder 似乎没有.Conventions,谷歌只返回较旧的 EF 4 尽管 EF 6 结果。

如何在实体框架 7 中指定ON DELETE NO ACTION约束?

编辑:Oleg 提供的答案显然会按外键执行,但我想全局执行此操作,因为使用一行代码全局声明它会容易得多,然后必须为我最终拥有的数百个关系中的每一个指定代码。

编辑 2:奥列格的代码

public class ChangeOrder
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    public Int16? ApprovedByID { get; set; }
    public Byte ApprovalStatusID { get; set; }
    public Int16 AssignedToID { get; set; }
    public Int16 CreatedByID { get; set; }
    public Byte CurrentStatusID { get; set; }
    public DateTime? DateApproved { get; set; }
    public DateTime? EndDate { get; set; }
    public Byte ImpactID { get; set; }
    public Byte PriorityID { get; set; }
    public DateTime? StartDate { get; set; }
    public Byte TypeID { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public string ReasonForChange { get; set; }
    [ForeignKey("ApprovedByID")]
    public User ApprovedBy { get; set; }
    [ForeignKey("ApprovalStatusID")]
    public ChangeApprovalStatus ApprovalStatus { get; set; }
    [ForeignKey("AssignedToID")]
    public User AssignedTo { get; set; }
    [ForeignKey("CreatedByID")]
    public User CreatedBy { get; set; }
    [ForeignKey("ImpactID")]
    public ChangeImpact Impact { get; set; }
    [ForeignKey("PriorityID")]
    public ChangePriority Priority { get; set; }
    [ForeignKey("TypeID")]
    public ChangeType ChangeType { get; set; }
    [ForeignKey("CurrentStatusID")]
    public ChangeStatus CurrentStatus { get; set; }
}
public class JobSightDBContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelbuilder)
    {
        base.OnModelCreating(modelbuilder);
    }
    DbSet<ChangeApprovalStatus> ChangeApprovalStatus { get; set; }
    DbSet<ChangeImpact> ChangeImapct { get; set; }
    DbSet<ChangeOrder> ChangeOrders { get; set; }
    DbSet<ChangePriority> ChangePriorities { get; set; }
    DbSet<ChangeStatus> ChangeStatus { get; set; }
    DbSet<ChangeType> ChangeTypes { get; set; }
    DbSet<User> Users { get; set; }
}

在实体框架 7 中指定“删除时不执行任何操作”

在 GitHub 上挖掘并与那里的 MS 一位非常有耐心的人合作后,当前的解决方案是将其添加到 DbContext 中

protected override void OnModelCreating(ModelBuilder modelbuilder)
{
    foreach (var relationship in modelbuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
    {
        relationship.DeleteBehavior = DeleteBehavior.Restrict;
    }
    base.OnModelCreating(modelbuilder);
}

构造

modelBuilder.Entity("myNamespace.Models.ChangeOrder", b =>
    {
        b.HasOne("myNamespace.Models.User")
            .WithMany()
            .HasForeignKey("CreatedByID")
            .OnDelete(DeleteBehavior.Cascade);
    });

意志意味着用REFERENCES [dbo].[User] ([CreatedByID]) ON DELETE CASCADE创造FK_ChangeOrder_User_CreatedByID。它应该存在于迁移期间创建的YourContextModelSnapshot.cs protected override void BuildModel(ModelBuilder modelBuilder)中。我不确定我是否完全理解您的问题,但我认为您应该将此类结构添加到XXXModelSnapshot.cs或删除这里已经存在的不需要的构造。

更新:我看到您在模型中遇到了问题。您在 中具有以下属性

public Int16? ApprovedByID { get; set; }
public Int16 AssignedToID { get; set; }
public Int16 CreatedByID { get; set; }
// navigation properties
[ForeignKey("ApprovedByID")]
public User ApprovedBy { get; set; }
[ForeignKey("AssignedToID")]
public User AssignedTo { get; set; }
[ForeignKey("CreatedByID")]
public User CreatedBy { get; set; }

默认情况下,迁移尝试在所有属性上设置DeleteBehavior.Cascade

您可以通过更改 OnModelCreating 来覆盖该行为,这将为所有键设置DeleteBehavior.Restrict行为,或者仅在一个键上设置DeleteBehavior.CascadeDeleteBehavior.SetNull行为。例如,下面的代码在CreatedByID上使用DeleteBehavior.Cascade(在外键上创建ON DELETE CASCADE(和其他外键上使用DeleteBehavior.Restrict(外键上没有ON DELETE(:

public class JobSightDBContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelbuilder)
    {
        base.OnModelCreating(modelbuilder);
        modelbuilder.Entity(typeof (ChangeOrder))
            .HasOne(typeof (User), "ApprovedBy")
            .WithMany()
            .HasForeignKey("ApprovedByID")
            .OnDelete(DeleteBehavior.Restrict); // no ON DELETE
        modelbuilder.Entity(typeof (ChangeOrder))
            .HasOne(typeof (User), "AssignedTo")
            .WithMany()
            .HasForeignKey("AssignedToID")
            .OnDelete(DeleteBehavior.Restrict); // no ON DELETE
        modelbuilder.Entity(typeof (ChangeOrder))
            .HasOne(typeof (User), "CreatedBy")
            .WithMany()
            .HasForeignKey("CreatedByID")
            .OnDelete(DeleteBehavior.Cascade); // set ON DELETE CASCADE
    }
    DbSet<ChangeApprovalStatus> ChangeApprovalStatus { get; set; }
    DbSet<ChangeImpact> ChangeImapct { get; set; }
    DbSet<ChangeOrder> ChangeOrders { get; set; }
    DbSet<ChangePriority> ChangePriorities { get; set; }
    DbSet<ChangeStatus> ChangeStatus { get; set; }
    DbSet<ChangeType> ChangeTypes { get; set; }
    DbSet<User> Users { get; set; }
}