web-dev-qa-db-ja.com

Entity Framework Core:FOREIGN KEY制約の導入により、サイクルまたは複数のカスケードパスが発生することがある

Code FirstアプローチでEntity Framework Coreを使用していますが、データベースの更新時に次のエラーを受け取ります。

テーブル 'AnEventUsers'にFOREIGN KEY制約 'FK_AnEventUsers_Users_UserId'を導入すると、サイクルまたは複数のカスケードパスが発生する場合があります。 ON DELETE NO ACTIONまたはON UPDATE NO ACTIONを指定するか、他の外部キー制約を変更します。制約またはインデックスを作成できませんでした。以前のエラーを参照してください。

私のエンティティは次のとおりです。

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; }
}

私が考えた問題は、ユーザーを削除するとAnEventへの参照が削除され、AnEventUserへの参照も削除されることでした。ただし、次のようにして、UserからAnEventUserへの削除カスケードを削除します。

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

しかし、エラーは解決されません、誰が間違っているかわかりますか?ありがとう!

9
Mu2tini

OnModelCreatingのサンプルコードでは、modelBuilder.Entity<AnEventUser>().HasOne(e => e.User)...を2回宣言しています:メソッドの開始時と終了時。

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

}

2番目の呼び出しが最初にオーバーライドされます。それを除く。

13
Dmitry

これは私がドミトリーの答えからしたことです、

そしてそれは私のために働いた。

クラス:

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
Bharat

私の場合、これらのソリューションは機能しませんでしたが、方法を見つけました。それが安全かどうかはまだよくわかりませんが、削除で起こっていることがあります。そこで、オーバーライドを行う代わりに、生成された移行ファイルを変更しました。

onDelete: ReferentialAction.Cascade

上記のすべてのオーバーライドが機能しないため、これを行った理由は、Cascading of Deleteに関連するコードを手動で削除したためです。

エラーで言及されている特定の関係を確認するだけで、すぐに進むことができます。

これが私の問題と同じ問題を抱えている一部の人々に役立つことを願っています。

0
Siege21x