Основная таблица привязки Entity Framework Core

entity-framework entity-framework-core entity-relationship

Вопрос

У меня есть класс под названием 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> 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 optional (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();

Вы можете сделать это за одну транзакцию



Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему