Самореференсный рекурсивный код отношений «многие ко многим» сначала Entity Framework - PullRequest
42 голосов
/ 26 февраля 2011

Кажется, я вообще не могу заставить это работать

class Member
{
    public virtual IList<Member> Friends { get; set; }
    [Key]
    public int MemberId { get; set; }
    public string Name{ get; set; }
}

Я пытался добавить сопоставления, но тщетно.Есть ли способ сделать это с CTP5?

Ответы [ 4 ]

61 голосов
/ 26 февраля 2011

По соглашению Code First будет принимать однонаправленные ассоциации как один ко многим. Поэтому вам нужно использовать свободный API, чтобы Code First знал, что вы хотите иметь самосвязанную связь «многие ко многим»:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Member>().HasMany(m => m.Friends).WithMany();
}

Примечание. В CTP5 существует известная ошибка, которая не позволяет настраивать имена столбцов объединяемой таблицы в этом сценарии.

18 голосов
/ 23 июля 2014

Если я прав, вы можете повлиять на имя таблицы «многие ко многим» с помощью этого кода:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Member>().HasMany(m => m.Friends).WithMany().Map(m =>
        {
            m.MapLeftKey("MemberId");
            m.MapRightKey("FriendId");
            m.ToTable("MembersFriends");
        }
    );
}

надеюсь, это поможет.

2 голосов
/ 26 февраля 2011

Вы можете заставить это работать в EF 4 CTP5, используя Model-First, но CTP5 Code First содержит слишком много ошибок с самообращающимися и полиморфными конфигурациями запросов, чтобы использовать Code First для таких сценариев. Мортеза Манави (см. Другой ответ) задокументировал несколько из них в своем блоге.

0 голосов
/ 26 февраля 2011

Ваш пример - это не отношение многие ко многим, это скорее рекурсивные отношения.

Я не уверен, как это исправить.Но проблема с вашим кодом состоит в том, что вы получите два поля в одной строке с одинаковым именем.MemberId для идентификатора строки и MemberId для идентификатора друга.

Редактировать

Попробуйте сделать это так:

    class Member 
    { 
        [Key]
        public int MemberId { get; set; } 
        public string Name { get; set; }

        public virtual IList<FriendRelationship> Friends { get; set; } 

    }

    class FriendRelationship
    {
        [Key]
        public int RelationshipId { get; set; }

        public Member Friend { get; set; }
    }
...