簡體   English   中英

Entity Framework Core 3.0 - 創建一個自引用的多對多關系

[英]Entity Framework Core 3.0 - Creating a self-referencing many to many relationship

所以這是我的問題......我試圖創建的是一個自我引用的多對多關系。 基本上這里是我的 model。

public class InformationSystem
{
  public InformationSystem()
  {
     Systems = new HashSet<InformationSystem>();
     ParentSystems = new HashSet<InformationSystem>();
  }
 [Key()]
 public int InformationSystemID { get; set; }
 public string InformationSystemName { get; set; }
 //Navigation properties
 public virtual ICollection<InformationSystem> Systems { get; set; }
 public virtual ICollection<InformationSystem> ParentSystems { get; set; }
}

這個想法是一個系統可以有很多父母,父母可以有很多孩子。 我知道如何做一個自我引用的實體,許多孩子可以有一個父母。 讓我絆倒的是多對多的部分。 下面是我的 DbContext。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<InformationSystem>(entity =>
  {
    entity
       .HasMany(e => e.ParentSystems)
       .WithMany(e => e.Systems)
       .OnDelete(DeleteBehavior.Restrict);
  });

但是,在我的 DbContext 上,我收到一個錯誤,即.WithMany 不包含用於接受類型集合輸入的 with many 的定義。 我知道,當代碼首先創建遷移並更新數據庫時,基本上需要構建一個鏈接表。 我認為鏈接表將有兩列並且沒有鍵。 一列是 InformationSystemID,一列是 ParentInformationSystemID。 兩者都是外鍵。 我還知道,要使其正常工作,刪除行為應該受到限制,以便如果在鏈接表中刪除或更新條目,則該更改不會級聯(並創建循環)。 有人可以指出我需要做什么才能讓 EF Core 3 正確執行此操作的正確方向嗎? 如果我必須自己創建一個鏈接表,我將如何做 go? 我需要在我的 DbContext 中做什么? 我知道鏈接表看起來像這樣:
我將不勝感激。

public class InfoSysToParentInfoSys
{
  public int InfoSysID;
  public virtual InformationSystem InfoSys;

  public int ParentInfoSysID;
  public virtual InformationSystem ParentInfoSys;
}

在 EF Core 中,必須在 model 中包含一個實體來表示 M:N 關系中的連接表,然后將導航屬性添加到指向連接實體的多對多關系的任一側。

新表S:

public class InformationSystem
{
    public InformationSystem()
    {
    }

    [Key()]
    public virtual int InformationSystemID { get; set; }
    public virtual string InformationSystemName { get; set; }

    public virtual ICollection<InformationSystemRelation> Systems { get; set; }
    public virtual ICollection<InformationSystemRelation> ParentSystems { get; set; }

}


public class InformationSystemRelation
{
    public int ParentId { get; set; }
    public InformationSystem Parent { get; set; }

    public int ChildId { get; set; }
    public InformationSystem Child { get; set; }
}

映射:

modelBuilder.Entity<InformationSystemRelation>()
    .HasKey(x => new { x.ParentId, x.ChildId });

modelBuilder.Entity<InformationSystemRelation>()
    .HasOne(x => x.Parent)
    .WithMany(x => x.Systems)
    .HasForeignKey(x => x.ParentId)                    
    .OnDelete(DeleteBehavior.Restrict);


modelBuilder.Entity<InformationSystemRelation>()
    .HasOne(x => x.Child)
    .WithMany(x => x.ParentSystems)
    .HasForeignKey(x => x.ChildId)
    .OnDelete(DeleteBehavior.Restrict);

整個樣本:

class Program
{
    static void Main(string[] args)
    {
        var db = new MyDbContext();

        var is1 = new InformationSystem() { InformationSystemName = "is1" };
        var is2 = new InformationSystem() { InformationSystemName = "is2" };
        var is3 = new InformationSystem() { InformationSystemName = "is3" };
        var is4 = new InformationSystem() { InformationSystemName = "is4" };

        db.InformationSystems.Add(is1);
        db.InformationSystems.Add(is2);
        db.InformationSystems.Add(is3);
        db.InformationSystems.Add(is4);

        db.SaveChanges();

        var r1 = new InformationSystemRelation() { ParentId = 1, ChildId = 2 };
        var r2 = new InformationSystemRelation() { ParentId = 1, ChildId = 3 };
        var r3 = new InformationSystemRelation() { ParentId = 4, ChildId = 2 };
        var r4 = new InformationSystemRelation() { ParentId = 2, ChildId = 3 };
        var r5 = new InformationSystemRelation() { ParentId = 2, ChildId = 4 };

        db.InformationSystemRelations.Add(r1);
        db.InformationSystemRelations.Add(r2);
        db.InformationSystemRelations.Add(r3);
        db.InformationSystemRelations.Add(r4);
        db.InformationSystemRelations.Add(r5);

        db.SaveChanges();

        var o2 = db.InformationSystems.Include(x => x.Systems).Include(x => x.ParentSystems).Single(x => x.InformationSystemID == 2);
    }

}

public class InformationSystem
{
    public InformationSystem()
    {
    }

    [Key()]
    public virtual int InformationSystemID { get; set; }
    public virtual string InformationSystemName { get; set; }

    public virtual ICollection<InformationSystemRelation> Systems { get; set; }
    public virtual ICollection<InformationSystemRelation> ParentSystems { get; set; }

}

public class MyDbContext : DbContext
{

    public DbSet<InformationSystem> InformationSystems { get; set; }
    public DbSet<InformationSystemRelation> InformationSystemRelations { get; set; }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<InformationSystem>(entity =>
        {
            modelBuilder.Entity<InformationSystemRelation>()
                    .HasKey(x => new { x.ParentId, x.ChildId });

            modelBuilder.Entity<InformationSystemRelation>()
                .HasOne(x => x.Parent)
                .WithMany(x => x.Systems)
                .HasForeignKey(x => x.ParentId)
                .OnDelete(DeleteBehavior.Restrict);

            modelBuilder.Entity<InformationSystemRelation>()
                .HasOne(x => x.Child)
                .WithMany(x => x.ParentSystems)
                .HasForeignKey(x => x.ChildId)
                .OnDelete(DeleteBehavior.Restrict);
        });
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("data source=(local)\\SQLEXPRESS;Initial catalog=Test;Integrated security=SSPI");
        base.OnConfiguring(optionsBuilder);
    }
}

public class InformationSystemRelation
{
    public int ParentId { get; set; }
    public InformationSystem Parent { get; set; }

    public int ChildId { get; set; }
    public InformationSystem Child { get; set; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM