首页 文章

实体框架核心:如何解决引入FOREIGN KEY约束可能会导致循环或多个级联路径

提问于
浏览
8

我正在使用Entity Framework Core和Code First方法,但在更新数据库时收到以下错误:

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

我的实体是:

public class AnEvent
{
    public int AnEventId { get; set; }
    public DateTime Time { get; set; }
    public Gender Gender { get; set; }
    public int Duration { get; set; }
    public Category Category { get; set; }
    public int MinParticipants { get; set; }
    public int MaxParticipants { get; set; }
    public string Description { get; set; }
    public Status EventStatus { get; set; }
    public int MinAge { get; set; }
    public int MaxAge { get; set; }
    public double Longitude { get; set; }
    public double Latitude { get; set; }

    public ICollection<AnEventUser> AnEventUsers { get; set; }

    public int UserId { get; set; }
    public User User { get; set; }
}


public class User
{
    public int UserId { get; set; }
    public int Age { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Gender Gender { get; set; }
    public double Rating { get; set; }

    public ICollection<AnEventUser> AnEventUsers { get; set; }
}

public class AnEventUser
{
    public int AnEventId { get; set; }
    public AnEvent AnEvent { get; set; }

    public int UserId { get; set; }
    public User User { get; set; }

}

public class ApplicationDbContext:DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options):base(options)
    { }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AnEventUser>()
            .HasOne(u => u.User).WithMany(u => u.AnEventUsers).IsRequired().OnDelete(DeleteBehavior.Restrict);


        modelBuilder.Entity<AnEventUser>()
            .HasKey(t => new { t.AnEventId, t.UserId });

        modelBuilder.Entity<AnEventUser>()
            .HasOne(pt => pt.AnEvent)
            .WithMany(p => p.AnEventUsers)
            .HasForeignKey(pt => pt.AnEventId);

        modelBuilder.Entity<AnEventUser>()
            .HasOne(eu => eu.User)
            .WithMany(e => e.AnEventUsers)
            .HasForeignKey(eu => eu.UserId);

    }

    public DbSet<AnEvent> Events { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<AnEventUser> AnEventUsers { get; set; }
}

我想的问题是,如果我们删除User,将删除对AnEvent的引用,并且还将删除对AnEventUser的引用,因为AnEvent引用了AnEventUser,我们也获得了级联路径 . 但我删除了从User到AnEventUser的删除级联:

modelBuilder.Entity<AnEventUser>()
        .HasOne(u => u.User).WithMany(u => u.AnEventUsers).IsRequired().OnDelete(DeleteBehavior.Restrict);

但是错误没有得到解决,有人看到了什么问题吗?谢谢!

3 回答

  • 0

    OnModelCreating 中的示例代码中,您已经声明 modelBuilder.Entity<AnEventUser>().HasOne(e => e.User)... 两次:在方法开始时和结束时 .

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AnEventUser>()       // THIS IS FIRST
            .HasOne(u => u.User).WithMany(u => u.AnEventUsers).IsRequired().OnDelete(DeleteBehavior.Restrict);
    
    
        modelBuilder.Entity<AnEventUser>()
            .HasKey(t => new { t.AnEventId, t.UserId });
    
        modelBuilder.Entity<AnEventUser>()
            .HasOne(pt => pt.AnEvent)
            .WithMany(p => p.AnEventUsers)
            .HasForeignKey(pt => pt.AnEventId);
    
        modelBuilder.Entity<AnEventUser>()       // THIS IS SECOND.
            .HasOne(eu => eu.User)               // THIS LINES
            .WithMany(e => e.AnEventUsers)       //   SHOULD BE
            .HasForeignKey(eu => eu.UserId);     //   REMOVED
    
    }
    

    第二次调用首先覆盖 . 去掉它 .

  • 9

    这就是我从德米特里的回答中所做的,

    它对我有用 .

    类:

    public class EnviornmentControls
    {
        public int Id { get; set; }
        ...
    
        public virtual Environment Environment { get; set; }
    }
    

    这是映射

    public EnviornmentControlsMap(EntityTypeBuilder<EnviornmentControls> entity)
    {
            entity.HasKey(m => m.Id);           
    
            entity.HasOne(m => m.Environment)
                .WithMany(m => m.EnviornmentControls)
                .HasForeignKey(m => m.EnvironmentID)
                .OnDelete(DeleteBehavior.Restrict); // added OnDelete to avoid sercular reference 
    }
    
  • 2

    这些解决方案对我的情况不起作用,但我找到了一种方法 . 我不太确定它是否安全,但只是删除时发生了一些事情 . 所以我修改了生成的迁移文件,而不是重写 .

    onDelete: ReferentialAction.Cascade
    

    我这样做的原因是因为上面提到的所有重要内容对我不起作用所以我手动删除了与Cascading of Delete相关的代码 .

    只需检查错误中提到的具体关系,以便直接进行 .

    希望这能够帮助一些与我有同样问题的人 .

相关问题