Lukas Nys
Lukas Nys

Reputation: 435

How to fix 'Unable to determine the relationship represented by navigation property' error in Entity Framework

When I try to register a user on my .NET Core 2.1 website (using identity) I get the following error:

"InvalidOperationException: Unable to determine the relationship represented by navigation property 'City.ConnectionStartCity' of type 'ICollection'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.".

The reason this happens probably has nothing to do with identity, but registering and logging in is currently the only way I know how to trigger it.

I still want the properties City en ICollection<Connection> in my classes so I don't want to use the [NotMapped] attribute.

I searched on the internet and found that this is caused by a many-many relationship, I feel like this is not the case tho.

Class 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; }
}

Class 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; }
}

Class treinrittenContext (dbContext) extract:


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");
        });
       
        ...
    }

I expect this to work (since in my eyes it's a one-many relation), but it doesn't.

Upvotes: 33

Views: 118737

Answers (4)

Zahra
Zahra

Reputation: 2688

In my case I had a custom name for the ForeignKey fields and Entity Framework did not like my ParentId convention.

I was able to resolve this by using nameof(Parent):

public partial class Child
{
    public int Id { get; set; }

    public string Name { get; set; }

    [ForeignKey(nameof(Parent))]
    public int IdOfParent{ get; set; }

    public Parent? Parent{ get; set; }

}

Upvotes: 0

ihsan g&#252;&#231;
ihsan g&#252;&#231;

Reputation: 281

public class Entity
    {
        public int UserId { get; set; }
        [NotMapped]
        public virtual User User { get; set; }
    }

Just Added Like this.

Upvotes: 2

Shahzaib Hassan
Shahzaib Hassan

Reputation: 89

In my case, problem occurred because when of overriding OnModelCreating in DbContext and not calling base.OnModelCreating(builder).

Upvotes: 2

Dimitri
Dimitri

Reputation: 1271

UPDATE

You have multiple options here:

Option 1 with result 1

enter image description here

City Class becomes:

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; }
}

Connection Class becomes:

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; }     
}

Your OnModelCreating becomes:

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

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

OR you can do something like this as well wchich would be option 2 with results 2:

enter image description here

City Class becomes:

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; }
}

Connection Class becomes:

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; }     
}

And you don't have to do anything in your OnModelCreating.

Upvotes: 30

Related Questions