Your EF context is not properly configured. It doesn't have any primary keys and doesn't have any relations. EF doesn't work at all without primary keys or if you don't need them you have to include "NoPrimaryKey" statement. And no any query will run properly if your relations are not configured. You have to change your code to this:
The class ContactSkill should show what table are foreign keys of:
public class ContactSkill
{
[Key]
public int Id { get; set; }
public int ContactId { get; set; }
[ForeignKey(nameof(ContactId))]
[InverseProperty(nameof(ContactSkill.Contact.ContactSkills))]
public virtual Contact Contact { get; set; }
public int SkillId { get; set; }
[ForeignKey(nameof(SkillId))]
[InverseProperty(nameof(ContactSkill.Contact.ContactSkills))]
public virtual Skill Skill { get; set; }
}
And configure many-to-many relations in if fluent-api EF core context:
public class ApiContext : DbContext
{
public ApiContext()
{
}
public ApiContext(DbContextOptions<ApiContext> options)
: base(options)
{
}
public DbSet<Contact> Contacts { get; set; }
public DbSet<Skill> Skills { get; set; }
public DbSet<ContactSkill> ContactSkills { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ContactSkill>(entity =>
{
entity.HasOne(d => d.Contact)
.WithMany(p => p.ContactSkills)
.HasForeignKey(d => d.ContactId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_ContactSkill_Contact");
entity.HasOne(d => d.Skill)
.WithMany(p => p.ContactSkills)
.HasForeignKey(d => d.SkillId)
.HasConstraintName("FK_ContactSkill_Skill");
});
}
The class Contact should include primary key attribute and virual collection of ContactSkills:
public class Contact
{
public Contact()
{
ContactSkills = new HashSet<ContactSkill>();
}
[Key]
public int Id { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string FirstName { get; set; }
public string FullName { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string MobilePhoneNumber { get; set; }
[InverseProperty(nameof(ContactSkill.Contact))]
public virtual ICollection<ContactSkill> ContactSkills { get; set; }
}
The class Skill should include primary key attribute and virual collection of ContactSkills:
public class Skill
{
public Skill()
{
ContactSkills = new HashSet<ContactSkill>();
}
[Required]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int ExpertiseLevel { get; set; }
[InverseProperty(nameof(ContactSkill.Skill))]
public virtual ICollection<ContactSkill> ContactSkills { get; set; }
}