在实体框架7中指定ON DELETE NO ACTION?

Mat*_*ete 29 c# entity-framework-core

在Entity Framework 7中,当我尝试应用迁移时,我收到错误

在表'ChangeOrder'上引入FOREIGN KEY约束'FK_ChangeOrder_User_CreatedByID'可能会导致循环或多个级联路径.指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束.
无法创建约束.查看以前的错误.

我知道在旧版本的Entity Framework中你可以通过添加来解决这个问题

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
Run Code Online (Sandbox Code Playgroud)

到DbContext,但在EF7 modelBuilder似乎没有.Conventions它和谷歌只返回旧的EF 4虽然EF 6结果.

如何ON DELETE NO ACTION在Entity Framework 7中具体约束?

编辑:奥列格提供的答案显然是按照外键进行的,但是我想在全局范围内进行,因为使用一行代码来全局声明这一点会更容易,然后必须为每一个代码指定代码.我将最终拥有数百种关系.

编辑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; }
}
Run Code Online (Sandbox Code Playgroud)
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; }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*ete 53

在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);
}
Run Code Online (Sandbox Code Playgroud)

  • 不适合我:'DbModelBuilder'不包含'Model'的定义。 (4认同)
  • 这在EF Core 2.1中不起作用:( (3认同)
  • 这救了我的命!!!!!我遇到了很多建模 FK 问题。太感谢了!!!!!!!!!!!!!! (2认同)
  • 只是要添加一个注释,如果看不到SelectMany(默认情况下),请使用System.Linq添加; (2认同)

Ole*_*leg 15

那个工程

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

将意味着创造FK_ChangeOrder_User_CreatedByIDREFERENCES [dbo].[User] ([CreatedByID]) ON DELETE CASCADE.它应该存在protected override void BuildModel(ModelBuilder modelBuilder)YourContextModelSnapshot.cs迁移过程中创建的.我不确定我是否完全理解你的问题,但我认为你应该添加这样的构造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; }
Run Code Online (Sandbox Code Playgroud)

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

您可以通过更改来覆盖行为OnModelCreating,该DeleteBehavior.Restrict行为会设置所有键的行为,或者只设置一个键DeleteBehavior.CascadeDeleteBehavior.SetNull行为键.例如,下面的代码使用DeleteBehavior.Cascadeon CreatedByID(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; }
}
Run Code Online (Sandbox Code Playgroud)

  • @Olga是的,EF7默认行为是设置`ON DELETE CASCADE`我想覆盖它并删除该行为,因此默认变为`ON DELTE NO ACTION`.在EF6中,这是通过`modelBuilder.Conventions.Remove <OneToManyCascadeDeleteConvention>();`来完成的.你告诉我的是如何逐个为每个属性做.我需要知道的是如何设置`DeleteBehavior.Restrict`作为EF7的默认行为. (2认同)