且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Entity Framework Core 自引用表

更新时间:2023-02-02 22:54:26

您可以通过下一种方式来完成.首先,您应该为您的模型添加两个新属性 public virtual ListParentNextItems { 获取;放;}public virtual ListParentPreviousItems { 获取;放;}.所以你的模型将是这样的

You can do it in next way. First of all you should add two new properties to you model public virtual List<Item> ParentNextItems { get; set; } and public virtual List<Item> ParentPreviousItems { get; set; }. So your model will be something like this

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

然后你可以用下一种方式配置它

And than you can configure it in next way

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) 更改并编写下一个模型:

That's all. But if you want to achieve the same with attribute configuration, than you can skip void OnModelCreating(ModelBuilder modelBuilder) changes and just write next model:

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?),我在答案中做了相应的更改.

Update Also you should make PreviousItemId, NextItemId optional (Guid?), I did corresponding changes in my answer.

据我所知,您无法在一次 .SaveChanges() 行程中完成.创建第二个项目时,您应该已经将第一个项目保存到数据库中.(无论如何,这是另一个问题的主题)

And as far as I know, you just can't do it in one .SaveChanges() trip. When you create your second item you should already have first item saved into database. (anyway this is subject for another question)

但是无论如何,如果您将代码修改为类似的内容

But anyway if you modify you code to something like that

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

您可以在一次交易