实体框架核心自引用表

时间:2016-10-08 02:05:09

标签: entity-framework entity-relationship entity-framework-core

我有一个名为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 个答案:

答案 0 :(得分:1)

你可以用下一个方式来做。首先,您应该为模型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?),我在答案中做了相应的修改。

据我所知,你不能在一次.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();

您可以在一个transaction

中完成

答案 1 :(得分:0)

您不需要拥有 Collection,因为据我所知,您的目标是创建某种类型的 Two Way LinkedList。 A 能够通过向主模型添加 .HasOne() 来修复它。

     modelBuilder.Entity<Item>().HasOne(x => x.NextItem);
     modelBuilder.Entity<Item>().HasOne(x => x.PreviousItem);