簡體   English   中英

Entity Framework Core 自引用表

[英]Entity Framework Core self referencing table

我有一個名為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來處理對同一個表的兩個引用。

你可以用下一個方法來做。 首先,您應該向模型中添加兩​​個新屬性public virtual List<Item> ParentNextItems { get; set; } public virtual List<Item> ParentNextItems { get; set; } public virtual List<Item> ParentNextItems { get; set; }public virtual List<Item> ParentPreviousItems { get; set; } public virtual List<Item> ParentPreviousItems { 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?),我在答案中做了相應的更改。

據我所知,你不能在一次.SaveChanges()旅行中做到這一點。 創建第二個項目時,您應該已經將第一個項目保存到數據庫中。 (無論如何,這是另一個問題的主題)

但是無論如何,如果您將代碼修改為類似的內容

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();

您可以在一筆交易中完成

您不需要擁有 Collection,因為據我所知,您的目標是創建某種類型的Two Way LinkedList A 能夠通過將.HasOne()添加到主模型來修復它。

     modelBuilder.Entity<Item>().HasOne(x => x.NextItem);
     modelBuilder.Entity<Item>().HasOne(x => x.PreviousItem);
public int? DeaultNextStateId { get; set; }
public State DeaultNextState { get; set; }
public virtual ICollection<State> DeaultNextStates { get; set; }

public int? OkNextStateId { get; set; }
public State OkNextState { get; set; }
public virtual ICollection<State> OkNextStates { get; set; }

public int? NotOkNextStateId { get; set; }
public State NotOkNextState { get; set; }
public virtual ICollection<State> NotOkNextStates { get; set; }

modelBuilder.Entity<Models.Workflow.State>()
    .HasKey(x => x.Id);
modelBuilder.Entity<Models.Workflow.State>()
    .HasOne(x => x.DeaultNextState).WithMany(x => x.DeaultNextStates).HasForeignKey(x => x.DeaultNextStateId)
        .Metadata.DeleteBehavior = DeleteBehavior.Restrict;

modelBuilder.Entity<Models.Workflow.State>()
    .HasOne(x => x.OkNextState).WithMany(x => x.OkNextStates).HasForeignKey(x => x.OkNextStateId)
        .Metadata.DeleteBehavior = DeleteBehavior.Restrict;

modelBuilder.Entity<Models.Workflow.State>()
    .HasOne(x => x.NotOkNextState).WithMany(x => x.NotOkNextStates).HasForeignKey(x => x.NotOkNextStateId)
        .Metadata.DeleteBehavior = DeleteBehavior.Restrict;

暫無
暫無

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

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