【问题标题】:One to Many - FOREIGN KEY constraint may cause cycles or multiple cascade paths一对多 - FOREIGN KEY 约束可能导致循环或多个级联路径
【发布时间】:2019-09-11 06:56:36
【问题描述】:

我有一个 Dienstbulletin 类,它具有同一类 Persoon 的多个属性。 当我执行更新数据库命令时。我收到以下错误:

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

    public class Persoon : DefaultFields
    {
        [Required]
        [StringLength(50, ErrorMessage = "Naam mag niet langer zijn dan 50 karakters.")]
        public string Naam { get; set; }

        [Display(Name = "Type")]
        [Range(1, int.MaxValue, ErrorMessage = "Selecteer een correct type")]
        [Required]
        public TypePersoon TypePersoon { get; set; }

        [Required]
        public Boolean Actief { get; set; }

        [InverseProperty("Ogp")]
        public ICollection<Dienstbulletin> OgpCollection { get; set; }

        [InverseProperty("Obp")]
        public ICollection<Dienstbulletin> ObpCollection { get; set; }

        [InverseProperty("Rechercheur")]
        public ICollection<Dienstbulletin> RechercheurCollection { get; set; }

        [InverseProperty("Opsteller")]
        public ICollection<Dienstbulletin> OpstellerCollection { get; set; }

    }

public class Dienstbulletin : DefaultFields
    {
        [Required]
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
        public string Datum { get; set; }

        [Display(Name = "Ploeg")]
        [Required]
        public int PloegID { get; set; }
        public virtual Gebruiker Ploeg { get; set; }

        public int VoertuigID { get; set; }
        public virtual Voertuig Voertuig { get; set; }

        [Display(Name = "Opsteller")]
        [Required]
        [ForeignKey("Opsteller")]
        public int OpstellerID { get; set; }
        public Persoon Opsteller { get; set; }

        [Display(Name = "OGP met dienst")]
        [Required]
        [ForeignKey("Ogp")]
        public int OgpID { get; set; }
        public Persoon Ogp { get; set; }

        [Display(Name = "OBP met dienst")]
        [Required]
        [ForeignKey("Obp")]
        public int ObpID { get; set; }
        public Persoon Obp { get; set; }

        [Display(Name = "Rechercheur met dienst")]
        [Required]
        [ForeignKey("Rechercheur")]
        public int RechercheurID { get; set; }
        public Persoon Rechercheur { get; set; }

        [Column(TypeName = "varchar(MAX)")]
        [Display(Name = "Aandachtsvestigingen")]
        public string Aandachtspunten { get; set; }

        [Column(TypeName = "varchar(MAX)")]
        [Display(Name = "Bijkomende opdrachten")]
        public string BijkomendeOpdrachten { get; set; }

        #region Collections
        public virtual ICollection<Opdracht> OpdrachtCollection { get; set; }
        #endregion
    }


 public class DienstbulletinAppContext : DbContext
    {
        public DienstbulletinAppContext() : base("Dienstbulletin"){}
        public DbSet<Dienstbulletin> Dienstbulletin { get; set; }
        public DbSet<Voertuig> Voertuigen { get; set; }
        public DbSet<Opdracht> Opdrachts { get; set; }
        public DbSet<OpdrachtDetail> OpdrachtDetails { get; set; }
        public DbSet<Locatie> Locaties { get; set; }
        public DbSet<Gebruiker> Gebruikers { get; set; }
        public DbSet<Persoon> Personen { get; set; }
        public DbSet<OpdrachtType> OpdrachtTypes { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Dienstbulletin>()
                .HasRequired(c => c.Obp)
                .WithMany()
                .HasForeignKey(u => u.ObpID)
                .WillCascadeOnDelete(false);

            modelBuilder.Entity<Dienstbulletin>()
                .HasRequired(c => c.Ogp)
                .WithMany()
                .HasForeignKey(u => u.OgpID)
                .WillCascadeOnDelete(false);

            modelBuilder.Entity<Dienstbulletin>()
                .HasRequired(c => c.Rechercheur)
                .WithMany()
                .HasForeignKey(u => u.RechercheurID)
                .WillCascadeOnDelete(false);

            modelBuilder.Entity<Dienstbulletin>()
                .HasRequired(c => c.Opsteller)
                .WithMany()
                .HasForeignKey(u => u.OpstellerID)
                .WillCascadeOnDelete(false);

            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }

谁能解释我做错了什么以及如何解决这个问题?

【问题讨论】:

  • 关系“FK_dbo.Dienstbulletin_dbo.Persoon_OgpID”是级联关系,但这显然会导致多个级联路径或循环(无限循环)。您可以在OnModelCreating 中将此关系定义为非级联关系,或者如果父记录被删除,则使用 SET NULL 仅清除相关字段。
  • Steven,我如何在 On ModelCreating 中将这种关系定义为非级联?在我的迁移类中,外键是非级联的 .ForeignKey("dbo.Persoons", t => t.ObpID, cascadeDelete: true)
  • 检查我发布的答案。这有帮助吗?

标签: model-view-controller entity-framework-6


【解决方案1】:

以下是如何使用 Fluent API 为关系关闭级联删除的示例。只需将 Type1Type2 替换为正确的类型即可。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Type1>()
        .HasOne(i => i.Type2)
        .WithMany(c => c.Type1s)
        .OnDelete(DeleteBehavior.SetNull);
}

【讨论】:

【解决方案2】:

对我来说,解决方案是这样的:

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
 {
     modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
 }

发现于: https://forums.asp.net/t/2118372.aspx?Introducing+FOREIGN+KEY+constraint+FK_dbo+Customers_dbo+States_StateId+on+table+Customers+may+cause+cycles+or+multiple+cascade+paths+Specify+ON+DELETE+NO+ACTION+or+ON+UPDATE+NO+ACTION+or+modify+other+FOREIGN+KEY+constraints

【讨论】:

    猜你喜欢
    • 2011-05-08
    • 2013-10-22
    • 2017-08-02
    • 2019-10-20
    • 2018-12-14
    • 2018-08-08
    相关资源
    最近更新 更多