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, но это гипотетический сценарий, я не знаю вашу логику. Проверьте эти сообщения для получения дополнительной информации:

Теперь можно указать оба конца как необязательные, но один из них должен быть основным. Если это ваш случай, я предлагаю вам прокомментировать атрибуты аннотаций данных и настроить отношения с помощью 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);
   }

Я предлагаю вам прочитать эту страницу, чтобы лучше понять личные отношения.

Другие вопросы по тегам