Как исправить ошибку «Не удается определить связь, представленную свойством навигации» в Entity Framework

#c# #entity-framework #asp.net-core

#c# #entity-framework #asp.net-core

Вопрос:

Когда я пытаюсь зарегистрировать пользователя на моем веб-сайте .NET Core 2.1 (используя identity) Я получаю следующую ошибку:

«Исключение InvalidOperationException: не удается определить связь, представленную свойством навигации «Город.ConnectionStartCity’ типа ‘ICollection’. Либо настройте связь вручную, либо проигнорируйте это свойство, используя атрибут ‘[NotMapped]’ или используя ‘EntityTypeBuilder.Игнорировать» в «OnModelCreating».».

Причина, по которой это происходит, вероятно, не имеет ничего общего с идентификацией, но регистрация и вход в систему в настоящее время — единственный известный мне способ ее запуска.

Мне все еще нужны свойства City en ICollection<Connection> в моих классах, поэтому я не хочу использовать [NotMapped] атрибут.

Я поискал в Интернете и обнаружил, что это вызвано многими-многими отношениями, я чувствую, что это не тот случай, хотя.

Класс Connection :

 public partial class Connection
{
    public Connection()
    {
        ConnectionRoute = new HashSet<ConnectionRoute>();
    }

    public int Id { get; set; }
    public int StartCityId { get; set; }
    public int EndCityId { get; set; }
    public int AantalMinuten { get; set; }
    public double Prijs { get; set; }

    public Stad StartCity { get; set; }
    public Stad EndCity { get; set; }
    public ICollection<ConnectionRoute> ConnectionRoute{ get; set; }
}

  

Класс City :

 
public partial class City
{
    public City()
    {
        AspNetUsers = new HashSet<AspNetUsers>();
        Hotel = new HashSet<Hotel>();
        ConnectionStartCity = new HashSet<Connection>();
        ConnectionEndCity= new HashSet<Connection>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Country { get; set; }

    public ICollection<AspNetUsers> AspNetUsers { get; set; }
    public ICollection<Hotel> Hotel { get; set; }
    public ICollection<Connection> ConnectionStartCity { get; set; }
    public ICollection<Connection> ConnectionEndCity { get; set; }
}
  

Извлечение класса treinrittenContext (DbContext):

 
public virtual DbSet<City> City{ get; set; }

public virtual DbSet<Connection> Connection{ get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        ...

        modelBuilder.Entity<City>(entity =>
        {
            entity.Property(e => e.Country)
                .IsRequired()
                .HasMaxLength(255)
                .IsUnicode(false);

            entity.Property(e => e.Name)
                .IsRequired()
                .HasMaxLength(255)
                .IsUnicode(false);

            entity.HasMany(p => p.ConnectionStartcity)
                .WithOne(d => d.StartCity)
                .HasForeignKey(d => d.StartCityId);

            entity.HasMany(p => p.ConnectionEndCity)
                .WithOne(d => d.EndCity)
                .HasForeignKey(d => d.EndCityId);
        });

        ...

        modelBuilder.Entity<Connection>(entity =>
        {
            entity.HasOne(d => d.StartCity)
                .WithMany(p => p.ConnectionStartCity)
                .HasForeignKey(d => d.StartCityId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_Verbinding_BeginStad");

            entity.HasOne(d => d.EndCity)
                .WithMany(p => p.ConnectionEndCity)
                .HasForeignKey(d => d.EndCityId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_Verbinding_EindStad");
        });
       
        ...
    }
  

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

Комментарии:

1. Вам также следует подумать о своем именовании, коллекции должны быть множественными (meervoud), например, вашими наборами баз данных должны быть Connections amp; Cities, а также ваши свойства ConnectionStartCity amp; ConnectionEndCity. Что касается ошибки, возможно, из-за того, что вам не хватает [Требуется] Аннотации к вашему StartCity amp; EndCity.

2. @Dimitri, спасибо за совет по соглашениям об именовании. Добавление [обязательных] аннотаций к StartCity и EndCity в Connection не решило проблему.

Ответ №1:

Обновить

Здесь у вас есть несколько вариантов:

Вариант 1 с результатом 1

введите описание изображения здесь

Класс City становится:

 public partial class City
{
    public City()
    {           
        Connections = new HashSet<Connection>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Country { get; set; }

    public ICollection<Connection> Connections { get; set; }
}
  

Класс подключения становится:

 public partial class Connection
{
    public Connection()
    {
    }

    public int Id { get; set; }

    public int StartCityId { get; set; }
    public int EndCityId { get; set; }

    public int AantalMinuten { get; set; }
    public double Prijs { get; set; }     
}
  

Ваше OnModelCreating становится:

 modelBuilder.Entity<City>().HasMany(city => city.Connections)
                           .WithRequired().HasForeignKey(con => con.EndCityId);

modelBuilder.Entity<City>().HasMany(city => city.Connections)
                           .WithRequired().HasForeignKey(con => con.StartCityId);
  

ИЛИ вы также можете сделать что-то подобное, что было бы вариантом 2 с результатами 2:

введите описание изображения здесь

Класс City становится:

 public partial class City
{
    public City()
    {           
        Connections = new HashSet<Connection>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Country { get; set; }

    public ICollection<Connection> Connections { get; set; }
}
  

Класс подключения становится:

 public partial class Connection
{
    public Connection()
    {
    }

    public int Id { get; set; }

    public virtual ICollection<City> Cities { get; set; }

    public int AantalMinuten { get; set; }
    public double Prijs { get; set; }     
}
  

И вам не нужно ничего делать в вашем OnModelCreating.

Комментарии:

1. Я только что понял, что оставил некоторые слова непереведенными в своем вопросе. Это моя вина, извините! Я обновил ее, так что теперь это должно иметь больше смысла. Город — это просто таблица для городов (в моем случае Лондон, Брюссель, …), соединение должно быть соединением между двумя городами (например, «Лондон — Брюссель» или «Брюссель-Париж»). Итак, в City я хотел бы иметь список соединений, где город является начальной точкой, и список соединений, где город является конечной точкой. Полная модель базы данных (Stad = Город и Verbinding = Соединение): gyazo.com/8211bb2789e0f7a864aee1a6b9e21192

2. Когда я пробую первый вариант, я получаю эту ошибку во время сборки: «Не удается создать связь между ‘City. Соединение»и «Connection. EndCity», потому что уже существует связь между «Городом. Соединение»и «Conncection. StartCity». Свойства навигации могут участвовать только в одной связи.» Со вторым решением я теряю, какой город является отправной точкой, а какой — конечной. В этом случае важен их порядок.

3. Города коллекции должны быть виртуальными.

4. Я согласен со вторым решением, неприменимым для вашего случая. Что касается ошибки, странно, не происходит на моей стороне. У вас включена миграция? Если это так, обновите свою модель. Если нет, можете ли вы показать мне, что имеет ваш onmodelcreating и, в конечном итоге, как теперь выглядят ваши классы?

5. @Dimitri Спасибо за ваш ответ

Ответ №2:

В моем случае проблема возникла из-за переопределения OnModelCreating в DbContext и не вызова base.OnModelCreating(builder) .

Ответ №3:

Как и Шахзаиб, я исправил эту проблему для себя, вызвав base.OnModelCreating (builder) перед дополнительным кодом в переопределяющем методе

Комментарии:

1. Это должно быть опубликовано как комментарий, а не ответ

2. @Alberto Я согласен, но у меня недостаточно репутации, чтобы опубликовать комментарий, и все же хотел сообщить, что решение сработало