Entity Framework (Code First) Отношения "один ко многим" и "один к одному" (с двумя объектами). Как?
Я пытаюсь сделать это с EF Code First:
Там области две таблицы: пользователи и области. Один пользователь принадлежит одной требуемой области, а одна область может иметь ноль или одного пользователя (в качестве администратора). Затем:
Пользователи *..1 Области и Пользователи 0..1 Области
Класс Users:
public class User {
public int UserId { get; set; }
public string Name { get; set; }
[ForeignKey("Area")]
public int AreaId { get; set; }
[InverseProperty("Users")]
public virtual Area Area { get; set; }
public virtual Area AreaTitular { get; set; }
}
Класс Areas:
public class Area {
public int AreaId { get; set; }
public string Name { get; set; }
public List<User> Users { get; set; }
[ForeignKey("User")]
public int? UserId { get; set; }
[InverseProperty("AreaTitular")]
public virtual User User{ get; set; }
}
И ошибка в команде update-database:
Невозможно определить основной конец ассоциации между типами TestEntityFrameworkCodeFirst.Model.Area и TestEntityFrameworkCodeFirst.Model.User. Основной конец этой ассоциации должен быть явно сконфигурирован с использованием API свободного взаимодействия или аннотаций данных.
Любая помощь будет очень ценится:)
Я не совсем уверен, что это нормально:
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Area>()
.HasOptional(i => i.User)
.WithOptionalDependent();
base.OnModelCreating(modelBuilder);
}
Просто добавил это в OnModelCreating в классе Context. И вот как это выглядит в SQL Server:
1 ответ
Проблема заключается в конфигурации ваших отношений один-к-одному, потому что один конец должен быть основным, а второй конец должен быть зависимым. Когда вы конфигурируете этот тип отношений, Entity Framework требует, чтобы первичный ключ зависимого также был внешним ключом. Так что не отображайте UsuarioId
как FK, в противном случае EF требует, чтобы FK тоже был PK (прокомментируйте это свойство). Другая проблема в том, что EF не знает, кто является главным в ваших отношениях. Чтобы определить, кто является основным, используйте Required
приписывать. Если вы, например, добавите этот атрибут над AreaTitular
Вы указываете, что для создания User
, AreaTitular
свойство должно быть установлено после сохранения изменений, поэтому ваш принципал в этом случае Area
и зависимость User
, но это гипотетический сценарий, я не знаю вашу логику. Проверьте эти сообщения для получения дополнительной информации:
- Необязательное отношение один к одному с использованием Entity Framework Code First
- Что означает основной конец ассоциации в отношении 1:1 в структуре Entity
Теперь можно указать оба конца как необязательные, но один из них должен быть основным. Если это ваш случай, я предлагаю вам прокомментировать атрибуты аннотаций данных и настроить отношения с помощью Fluent Api следующим образом:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasRequired(a => a.Area)
.WithMany(c => c.Usuarios)
.HasForeignKey(a => a.AreaId);
modelBuilder.Entity<Area>()
.HasOptional(a => a.Usuario)
.WithOptionalPrincipal(u => u.AreaTitular);
}
Я предлагаю вам прочитать эту страницу, чтобы лучше понять личные отношения.