Один ко многим с таблицей соединений и необязательным отношением в Entity Framework 4.1 Fluent API - PullRequest
5 голосов
/ 12 августа 2011

Снова с устаревшей базой данных, которую нельзя изменить, и с использованием Entity Framework 4.1 с Fluent API только для чтения данных.

public class Client
{
  [Key]
  public int ClientID { get; set; }
  public string Name { get; set ;}

  public virtual ICollection<Phone> Phones { get; set; }
}

public class Phone
{
  [Key]
  public int PhoneID { get; set; }
  public string Number { get; set; }

  public virtual Client Client { get; set; }
}

public class ClientPhone
{
  [Key]
  [Column(Order=0)]
  public int ClientID { get; set; }

  [Key]
  [Column(Order=1)]
  public int PhoneID { get; set; }
}

Я хочу, чтобы у Клиента было много Телефонов, но у Телефонов должен быть только дополнительный Клиент. Примечание. Телефоны должны иметь только 0 | 1 клиента. Я не хочу много ко многим. Поэтому я попробовал следующее:

modelBuilder.Entity<Client>()
  .HasMany(c => c.Phones)
  .WithOptional(p => p.Client)
  .Map(m =>
    {
      m.MapKey("ClientID");
      m.ToTable("ClientPhone");
    });

modelBuilder.Entity<Phone>()
  .HasOptional(p => p.Client)
  .WithMany(c => c.Phones)
  .Map(m =>
    {
      m.MapKey("PhoneID");
      m.ToTable("ClientPhone");
    });

Я пробовал пару перестановок, обычно получая сообщение об ошибке «Каждое имя свойства в типе должно быть уникальным».

Спасибо за помощь.

РЕДАКТИРОВАТЬ С ОТВЕТОМ

Вот модификации, которые я внес в классы сущностей. Можно перейти от одного клиента ко многим телефонам и от одного телефона к одному клиенту , но вы должны пройти через таблицу соединения ClientPhone.

[Table("Client")]
public class Client
{
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int ClientID { get; set; }

  public string Name { get; set ;}

  public virtual ICollection<Phone> Phones { get; set; } // Client has * Phones
}

[Table("Phone")]
public class Phone
{
  [Key]
  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  public int PhoneID { get; set; }

  public string Number { get; set; }

  public virtual Client Client { get; set; } // Phone has 0|1 Client
}

[Table("ClientPhone")]
public class ClientPhone
{
  // Removed the Key attribute
  public int ClientID { get; set; }

  [Key] // Left the Key on the 0|1 side
  [ForeignKey("Phone")]
  public int PhoneID { get; set; }

  public virtual Client Client { get; set; } // One Client
  public virtual Phone Phone { get; set; } // One Phone
}

Ответы [ 2 ]

5 голосов
/ 12 августа 2011

вам не нужно указывать отношения между телефоном и клиентом два раза здесь. Просто используйте только один такой.

modelBuilder.Entity<Client>().HasMany(c => c.Phones).WithMany(i => i.Clients)
                .Map(t => t.MapLeftKey("PhoneID")
                    .MapRightKey("ClientID")
                    .ToTable("ClientPhone"));

вам не нужно иметь модели для сопоставления таблиц отношений, таких как "ClientPhone", потому что об этом позаботится EF. Если у вас есть устаревшая база данных, вы можете настроить сопоставления, как в моем ответе. И как @Ladislav Mrnka сказал, что для отношения один-ко-многим на уровне базы данных вы не хотите хранить отдельную таблицу для отношений. Для этого

public class Client
{
  [Key]
  public int ClientID { get; set; }
  public string Name { get; set ;}

  public virtual ICollection<Phone> Phones { get; set; }
}

public class Phone
{
  [Key]
  public int PhoneID { get; set; }
  public string Number { get; set; }

  public virtual Client Client { get; set; }
}

этого будет достаточно с EF. Он создаст две таблицы со столбцом clientId в таблице Phone , чтобы сохранить связь.

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

Если вы хотите сохранить отношения один-ко-многим, я думаю, вы можете определить на уровне домена отношение многие-ко-многим (у телефона много клиентов, а у клиента много телефонов в модельных предложениях), а на бизнес-уровне добавить проверки для сохранения только одного клиента для телефона .

1 голос
/ 12 августа 2011

Отношение один-ко-многим не имеет таблицы соединения (соединения).Если ваша база данных использует соединительную таблицу для подключения клиента к телефону, вы должны использовать отношение «многие ко многим» (в телефоне может быть много клиентов), как описано @Jayantha.

...