Определение нескольких внешних ключей для одной и той же таблицы в корневом коде Entity First
У меня есть два объекта в моем приложении MVC, и я заполнил базу данных с помощью подхода Entity Framework 6 Code First. В студенческой организации есть два идентификатора города; один из них для BirthCity, другой для WorkCity. Когда я определяю foreign keys, как указано выше, после миграции создается дополнительный столбец с именем City_ID в таблице Student. Id там ошибка или как определить эти FK? Заранее спасибо.
Студент:
public class Student { public int ID { get; set; } public string Name { get; set; } public string Surname { get; set; } public int BirthCityID { get; set; } public int LivingCityID { get; set; } [ForeignKey("BirthCityID")] public virtual City BirthCity { get; set; } [ForeignKey("LivingCityID")] public virtual City LivingCity { get; set; } }
- Ограничение внешнего ключа MySQL 5.5 не выполняется, если существует внешний ключ
- Как вы применяете ограничения внешнего ключа в SQLite через Java?
- Определение нескольких внешних ключей в одной таблице для многих таблиц
- Рубин на рельсах. Как использовать метод Active Record .build в: относится к отношениям?
- составной ключ как внешний ключ
Город:
public class City { public int ID { get; set; } public string CityName { get; set; } public virtual ICollection Students { get; set; } }
- Ограничить выбор внешнего ключа при выборе в встроенной форме в admin
- Ошибка Mysql 1452 - Невозможно добавить или обновить дочернюю строку: ограничение внешнего ключа не выполняется
- Как просмотреть все foreign keys таблицы или столбца?
- Внешний ключ MySQL для использования NULL?
- Инструкция INSERT противоречит ограничению FOREIGN KEY - SQL Server
- MySQL Создание таблиц с внешними ключами, дающих errno: 150
- Ограничения внешнего ключа MySQL, каскадное удаление
- Моделирование базы данных полиморфных ассоциаций - сначала против первого кода
Для достижения того, что вы хотите, вам нужно предоставить некоторую дополнительную конфигурацию. Код Первое соглашение может идентифицировать двунаправленные отношения, но не тогда, когда есть несколько двунаправленных отношений между двумя объектами. Вы можете добавить конфигурацию (используя annotations данных или Fluent API ), чтобы представить эту информацию к строителю модели. С аннотациями данных вы будете использовать аннотацию InverseProperty
. С Fluent API вы будете использовать комбинацию методов Has
/ With
чтобы указать правильные концы этих отношений.
Использование аннотаций данных может быть следующим:
public class Student { public int ID { get; set; } public string Name { get; set; } public string Surname { get; set; } public int BirthCityID { get; set; } public int LivingCityID { get; set; } [ForeignKey("BirthCityID")] [InverseProperty("Students")] public virtual City BirthCity { get; set; } [ForeignKey("LivingCityID")] public virtual City LivingCity { get; set; } }
Таким образом вы явно указываете, что хотите связать BirthCity
навигации BirthCity
со свойством « BirthCity
Students
в другом конце отношения.
Использование Fluent Api может быть следующим:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity().HasRequired(m => m.BirthCity) .WithMany(m => m.Students).HasForeignKey(m=>m.BirthCityId); modelBuilder.Entity ().HasRequired(m => m.LivingCity) .WithMany().HasForeignKey(m=>m.LivingCityId); }
С помощью этого последнего решения вам не нужно использовать какой-либо аттрибут.
Теперь предложение @ChristPratt in имеет коллекцию Student
в вашем classе City
для каждого отношения действительно полезно. Если вы это сделаете, то конфигурации с использованием аннотаций данных могут быть следующими:
public class Student { public int ID { get; set; } public string Name { get; set; } public string Surname { get; set; } public int BirthCityID { get; set; } public int LivingCityID { get; set; } [ForeignKey("BirthCityID")] [InverseProperty("BirthCityStudents")] public virtual City BirthCity { get; set; } [ForeignKey("LivingCityID")] [InverseProperty("LivingCityStudents")] public virtual City LivingCity { get; set; } }
Или используя Fluent Api, следуя той же идее:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity().HasRequired(m => m.BirthCity) .WithMany(m => m.BirthCityStudents).HasForeignKey(m=>m.BirthCityId); modelBuilder.Entity ().HasRequired(m => m.LivingCity) .WithMany(m => m.LivingCityStudents).HasForeignKey(m=>m.LivingCityId); }
Sheesh. Это был долгий день. На самом деле на самом деле очень большая, вопиющая проблема с вашим кодом, что я полностью пропустил, когда прокомментировал.
Проблема в том, что вы используете единую коллекцию студентов в City
. Что на самом деле происходит здесь, так это то, что EF не может решить, какой внешний ключ должен на самом деле отображать эту коллекцию, поэтому он создает другой внешний ключ, специально предназначенный для отслеживания этих отношений. Затем, по сути, у вас нет свойств навигации для коллекций студентов, полученных из BirthCity
и LivingCity
.
Для этого вам нужно спуститься до полной конфигурации, так как нет возможности правильно настроить это, используя только annotations данных. Вам также понадобится дополнительная коллекция студентов, чтобы вы могли отслеживать оба отношения:
public class City { ... public virtual ICollection BirthCityStudents { get; set; } public virtual ICollection LivingCityStudents { get; set; } }
Затем для Student
:
public class Student { ... public class StudentMapping : EntityTypeConfiguration { public StudentMapping() { HasRequired(m => m.BirthCity).WithMany(m => m.BirthCityStudents); HasRequired(m => m.LivingCity).WithMany(m => m.LivingCityStudents); } } }
И, наконец, в вашем контексте:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new Student.StudentMapping()); }