EF 4.1 Code First Таблица отношений - PullRequest
1 голос
/ 06 ноября 2011

Настройка

Использование MVC 3 + Первый код

Вот мои занятия

public class Member
    {
        [Key]
        public Guid ID { get; set; }

        [Required]
        public String Email { get; set; }

        [Required]
        public String FirstName { get; set; }

        [Required]
        public String LastName { get; set; }

        public String Sex { get; set; }

        public String Password { get; set; }

        public String PasswordSalt { get; set; }

        public DateTime RegisterDate { get; set; }

        public DateTime LastOnline { get; set; }

        public String SecurityQuestion { get; set; }

        public String SecurityAnswer { get; set; }

        public virtual ICollection<FamilyMember> Families { get; set; }

        public virtual ICollection<Relationship> Relationships { get; set; }


    }


public class Relationship
    {
        [Key]
        public Guid ID { get; set; }

        [ForeignKey("Member1")]
        public Guid Member1ID { get; set; }

        [ForeignKey("Member2")]
        public Guid Member2ID { get; set; }

        public Guid RelationshipTypeID { get; set; }

        public virtual RelationshipType RelationshipType { get; set; }

        public virtual Member Member1 { get; set; }

        public virtual Member Member2 { get; set; }

    }

Вот проблема

Таблица базы данных «Связь» создается со следующими столбцами:

ID, Member1ID, Member2ID, RelationshipTypeID, Member_ID

Почему создается столбец Member_ID ?

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

Буду признателен за любую помощь!

1 Ответ

2 голосов
/ 07 ноября 2011

Member_ID - столбец внешнего ключа, созданный EF для свойства навигации Member.Relationships. Он принадлежит третьей ассоциации от Member.Relationships, ссылающейся на конечную точку, которая не отображается в вашей Relationship сущности. Это отношение не имеет ничего общего с двумя другими отношениями из Relationship.Member1 и Relationship.Member2, которые также имеют конечную точку, не указанную в Member.

Полагаю, это не то, что вы хотите. Для создания ассоциации вам всегда нужно пар конечных точек в двух объектах. Одна конечная точка всегда является свойством навигации. Вторая конечная точка может также быть свойством навигации, но это не обязательно, вы можете опустить второе свойство навигации.

Теперь, что невозможно, это связать два навигационных свойства (Member1 и Member2) в одном объекте с одним навигационным свойством (Relationships) в другая сущность. Это то, что вы пытаетесь сделать, по-видимому.

Я предполагаю, что ваше свойство Member.Relationships должно выражать, что участник является либо Member1, либо Member2 в отношениях, либо что он участвует в отношениях, независимо от того, если как Member1 или Member2.

К сожалению, вы не можете выразить это в модели соответствующим образом. Вы должны ввести что-то вроде RelationsshipsAsMember1 и RelationsshipsAsMember2, и для этих двух коллекций вы можете использовать атрибут InverseProperty, как показано в другом вопросе. Кроме того, вы можете добавить вспомогательное свойство, которое объединяет две коллекции. Но это не сопоставленное свойство, а только для чтения:

public class Member
{
    // ...

    [InverseProperty("Member1")]
    public virtual ICollection<Relationship> RelationshipsAsMember1 { get; set; }
    [InverseProperty("Member2")]
    public virtual ICollection<Relationship> RelationshipsAsMember2 { get; set; }

    public IEnumerable<Relationship> AllRelationships
    {
        get { return RelationshipsAsMember1.Concat(RelationshipsAsMember2); }
    }
}

Доступ к AllRelationships приведет к тому, что два запроса и обращения к базе данных (с отложенной загрузкой) сначала загрузят обе коллекции, прежде чем они будут объединены в памяти.

При таком отображении столбец Member_ID исчезнет, ​​и вы получите только два ожидаемых столбца внешнего ключа Member1ID, Member2ID, потому что теперь у вас есть только две ассоциации, а не три.

Можно также подумать, нужен ли вам вообще набор Relationships в сущности Member. Как сказано, навигационные свойства с обеих сторон не требуются. Если вам редко требуется переходить от члена к его отношениям, вы можете получить отношения также с запросами из набора Relationship, например:

var relationships = context.Relationships
    .Where(r => r.Member1ID == givenMemberID || r.Member2ID == givenMemberID)
    .ToList();

... или ...

var relationships = context.Relationships
        .Where(r => r.Member1ID == givenMemberID)
    .Concat(context.Relationships
        .Where(r => r.Member2ID == givenMemberID)
    .ToList();

Это даст вам все отношения, в которых участвует участник с ID = givenMemberID, без необходимости сбора навигации по сущности Member.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...