Entity Framework 4.3 сначала кодирует много-много-много, используя одни и те же таблицы - PullRequest
30 голосов
/ 25 февраля 2012

У меня есть такая модель, как

public class User
{
    [Key]
    public long UserId { get; set; }

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

    public virtual ICollection<Town> Residencies { get; set; }

    public virtual ICollection<Town> Mayorships { get; set; }
}

и

public class Town
{
    [Key]
    public long TownId { get; set; }

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

    public virtual ICollection<User> Residents { get; set; }
    public virtual ICollection<User> Mayors { get; set; }
}

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

Вместо этого я получаю два FK UserIds в таблице Town и два FK TownIds в таблице User.

Есть какие-нибудь идеи, как заставить EF увидеть их в двух-многих-многих отношениях?

Спасибо

1 Ответ

31 голосов
/ 25 февраля 2012

Ну, EF не имеет какого-либо алгоритма распознавания слов и грамматики, который потребовался бы для определения того, что вы (вероятно) хотите, чтобы User.Residencies и Town.Residents образовывали пару навигационных свойств и User.Mayorships и Town.Mayors образуют вторую пару.Поэтому предполагается, что у вас есть четыре отношения один-ко-многим, и что каждое из четырех свойств навигации принадлежит одному из отношений.(Это причина четырех внешних ключей, которые вы видели в таблицах базы данных.)

Это стандартное предположение не то, что вам нужно, поэтому вы должны явно определить отношения, чтобы переопределить это стандартное соглашение:

Либо с аннотациями данных:

public class User
{
    [Key]
    public long UserId { get; set; }

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

    [InverseProperty("Residents")]
    public virtual ICollection<Town> Residencies { get; set; }

    [InverseProperty("Mayors")]
    public virtual ICollection<Town> Mayorships { get; set; }
}

Или с Fluent API:

modelBuilder.Entity<User>()
    .HasMany(u => u.Residencies)
    .WithMany(t => t.Residents)
    .Map(x =>
    {
        x.MapLeftKey("UserId");
        x.MapRightKey("TownId");
        x.ToTable("TownResidents");
    });

modelBuilder.Entity<User>()
    .HasMany(u => u.Mayorships)
    .WithMany(t => t.Mayors)
    .Map(x =>
    {
        x.MapLeftKey("UserId");
        x.MapRightKey("TownId");
        x.ToTable("TownMayors");
    });

Преимущество Fluent API заключается в том, что вы можете контролировать имя таблицы ссылок (и ключимена столбцов).Вы не можете определить эти имена с аннотациями данных.

...