Использование Entity Framework для получения группы с подгруппами, каждая со своими собственными подгруппами

Я строю иерархию групп для представления организационной структуры. У меня есть одна группа верхнего уровня, которая затем имеет ряд подгрупп. Каждая подгруппа может иметь любое количество подгрупп и так далее.

Я создал базу данных sql с двумя таблицами.

Группы со следующими столбцами.

  • Идентификатор (целое число)
  • Описание (nvarchar(max))

GroupChildren со следующими столбцами.

  • Идентификатор (целое число)
  • Идентификатор группы (целое число)
  • ChildGroupId (целое число)

Например, если в группе 1 есть две подгруппы, группа 2 и группа 3, в таблице групп будет 3 записи.

  • Идентификатор - 1, Описание - Группа 1
  • Идентификатор - 2, Описание - Группа 2
  • Идентификатор - 3, Описание - Группа 3

В таблице GroupChildren будет 2 записи.

  • Id - идентификатор первичного ключа, GroupId - 1, ChildGroupId - 2
  • Id - идентификатор первичного ключа, GroupId - 1, ChildGroupId - 3

Это связывает две мои дочерние группы с группой 1. У меня есть два класса POCO для представления этого, которые следующие:

public class Group
{
    public int Id { get; set; }
    public string Description { get; set; }
    public virtual ICollection<GroupChild> GroupChildren { get; set; }
}

public class GroupChild
{
    public int Id { get; set; }
    public int GroupId { get; set; }
    public Group ChildGroup { get; set; }
}

Я создал картографы для обоих этих классов, которые настроены следующим образом.

internal class GroupMapper : EntityTypeConfiguration<Group>
{
    internal GroupMapper()
    {
        HasKey(t => t.Id);

        Property(t => t.Id).HasColumnName("Id").IsRequired();
        Property(t => t.Description).HasColumnName("Description").IsRequired();

        ToTable("Groups");
    }
}

internal class GroupChildMapper : EntityTypeConfiguration<GroupChild>
{
    internal GroupChildMapper()
    {
        HasKey(g => g.Id);

        Property(g => g.Id).HasColumnName("Id").IsRequired();
        Property(g => g.GroupId).HasColumnName("GroupId").IsRequired();

        HasRequired(g => g.ChildGroup)
            .WithMany()
            .Map(x => x.MapKey("ChildGroupId"))
            .WillCascadeOnDelete(false);

        ToTable("GroupChildren");
    }
}

Чтобы получить группу и подгруппы, которые я вызываю

return GetDbSet<Group>()
    .Where(c => c.Id == id)
    .Single();

Это возвращает группу с идентификатором и описанием, но я получаю следующую ошибку при просмотре свойства GroupChildren

Недопустимое имя столбца "Group_Id".
Недопустимое имя столбца "Group_Id".

Столбец «Group_Id» не существует ни в коде, ни в базе данных. Я пытался решить эту проблему, просматривая другие сообщения, и некоторые предполагают, что это способ, которым EF интерпретирует значения первичного/внешнего ключа, но я не могу найти, как я могу это решить?

Спасибо


person Dave Shaw    schedule 22.11.2012    source источник
comment
Ваша модель работает, когда я пробую ее в VS2012, EF5. В ChildGroup есть столбец Group_Id. Однако, когда я добавляю Group и добавляю к нему несколько объектов GroupChild, я получаю, что HierachyDb.GroupChildren' участвует в отношении "GroupChild_ChildGroup". 0 связанных 'GroupChild_ChildGroup_Target' были найдены. 1 Ожидается «GroupChild_ChildGroup_Target». Но прежде чем пытаться это исправить, позвольте мне спросить: почему не простая иерархия с одним Group классом с Groups коллекцией? Ваша модель с прерывистыми классами довольно неуклюжа для иерархии. И ребенок может быть родителем своего собственного родителя!   -  person Gert Arnold    schedule 23.11.2012
comment
Герт, спасибо за ответ. Посмотрев на ваш ответ, я реорганизовал свой код, чтобы он работал более простым способом, который вы предложили. Изначально мы пошли по этому пути по той или иной причине, но в итоге это только добавило ненужной сложности. Большое спасибо   -  person Dave Shaw    schedule 23.11.2012


Ответы (1)


Причина, по которой вы получаете ошибку Invalid column name 'Group_Id', может заключаться в том, что вы перезаписываете имя столбца по умолчанию для внешнего ключа, объявляя public int GroupId { get; set; } в своем ChildGroup.

Попробуйте удалить public int GroupId { get; set; } из ChildGroup. Фреймворк должен позаботиться об отношениях за вас. После того, как вы выполнили миграцию данных в соответствии с обновленной моделью, вы должны увидеть, что платформа создала столбец Group_ID в вашей таблице Group, который устанавливает отношение.

person rouan    schedule 23.11.2012