Entity Frameworkコア自己参照テーブル

entity-framework entity-framework-core entity-relationship

質問

次のアイテムと前のItemを参照するItemというクラスがあります。

public class Item
{
    private Item() { }

    public Item(string itemName)
    {
        ItemId = Guid.NewGuid();
        ItemName = itemName;
    }

    public Guid ItemId { get; set; }
    public string ItemName { get; set; }

    public Guid NextItemId { get; set; }
    public virtual Item NextItem { get; set; }

    public Guid PreviousItemId { get; set; }
    public virtual Item PreviousItem { get; set; }

    public Guid GroupId { get; set; }
    public virtual Group Group { get; set; }
}

私はと呼ばれる別のテーブル持っているGroup 、それはそれにアイテムをグループ化するためのものですが。

public class Group
{
    private Group() { }
    public Group(string groupName)
    {
        GroupId = Guid.NewGuid();
        GroupName = groupName;
        GroupItems = new List<Item>();
    }

    public void AddGroupItem(Item item)
    {
        if (Items.Count == 0)
        {
            Items.Add(item);
        }
        else
        {
            item.PreviousItem = Items.Last();
            item.PreviousItemId = Items.Last().ItemId;
            Items.Last().NextItem = item;
            Items.Last().NextItemId = item.ItemId;

            Items.Add(item);
        }

    }

    public Guid GroupId { get; set; }
    public string GroupName { get; set; }
    public virtual IList<GroupItem> GroupItems { get; set; }
}

アイテムとそのグループを作成して保存する方法は次のとおりです。

Group group1 = new Group("first group");
Item item1 = new Item("item 1");
Item item2 = new Item("item 2");
Item item3 = new Item("item 3");

group1.AddItem(item1);
group1.AddItem(item2);
group1.AddItem(item3);

_context.Add(group1);
_context.SaveChanges();

OnModelCreatingを記述して、同じテーブルへの2つの参照を処理するにはどうすればよいですか。

人気のある回答

あなたは次の方法でそれを行うことができます。まず最初に、2つの新しいプロパティをモデルに追加する必要がありますpublic virtual List<Item> ParentNextItems { get; set; }public virtual List<Item> ParentPreviousItems { get; set; } 。あなたのモデルはこのようなものになります

public class Item
{
    private Item() { }

    public Item(string itemName)
    {
        ItemId = Guid.NewGuid();
        ItemName = itemName;
    }

    public Guid ItemId { get; set; }
    public string ItemName { get; set; }

    public Guid? NextItemId { get; set; }
    public virtual Item NextItem { get; set; }
    public virtual List<Item> ParentNextItems { get; set; }

    public Guid? PreviousItemId { get; set; }
    public virtual Item PreviousItem { get; set; }
    public virtual List<Item> ParentPreviousItems { get; set; }
}

そしてあなたがそれを次の方法で設定できるよりも

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Item>()
        .HasKey(x => x.ItemId);
    modelBuilder.Entity<Item>()
        .HasOne(x => x.NextItem).WithMany(x => x.ParentNextItems).HasForeignKey(x => x.NextItemId)
        .Metadata.DeleteBehavior = DeleteBehavior.Restrict;
    modelBuilder.Entity<Item>()
        .HasOne(x => x.PreviousItem).WithMany(x => x.ParentPreviousItems).HasForeignKey(x => x.PreviousItemId)
        .Metadata.DeleteBehavior = DeleteBehavior.Restrict;


    base.OnModelCreating(modelBuilder);
}

それで全部です。しかし、あなたが属性の設定で同じことを達成したい場合は、 void OnModelCreating(ModelBuilder modelBuilder)変更をスキップして次のモデルを書き込むよりも、

public class Item
{
    private Item() { }

    public Item(string itemName)
    {
        ItemId = Guid.NewGuid();
        ItemName = itemName;
    }

    [Key]
    public Guid ItemId { get; set; }
    public string ItemName { get; set; }

    public Guid? NextItemId { get; set; }

    [ForeignKey(nameof(NextItemId))]
    [InverseProperty(nameof(ParentNextItems))]
    public virtual Item NextItem { get; set; }

    [ForeignKey(nameof(NextItemId))]
    public virtual List<Item> ParentNextItems { get; set; }

    public Guid? PreviousItemId { get; set; }
    [ForeignKey(nameof(PreviousItemId))]
    [InverseProperty(nameof(ParentPreviousItems))]
    public virtual Item PreviousItem { get; set; }
    [ForeignKey(nameof(PreviousItemId))]
    public virtual List<Item> ParentPreviousItems { get; set; }
}

更新また、PreviousItemId、NextItemIdをオプション(Guid?)にする必要があります。私は答えに対応する変更を行いました。

そして、私が知る限り、あなたは1つの.SaveChanges()旅行でそれをすることはできません。 2番目のアイテムを作成するときは、すでにデータベースに保存されている最初のアイテムが必要です。 (とにかくこれは別の質問の対象です)

しかし、とにかくあなたがそのようなものにコードを修正したら

Group group1 = new Group("first group");
_context.Add(group1);
Item item1 = new Item("item 1");
group1.AddItem(item1);
_context.SaveChanges();
Item item2 = new Item("item 2");
group1.AddItem(item2);
_context.SaveChanges();
Item item3 = new Item("item 3");
group1.AddItem(item3);
_context.SaveChanges();

あなたは1つのトランザクションでそれを行うことができます



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ