MrMelodie
MrMelodie

Reputation: 63

All objects in the EntitySet must have unique primary > keys

I am facing an issue with entity framework code first and inheritance. Here’s my model :

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Student : Person
{
    // Student properties
}

public class Teacher : Person
{
    // Teacher properties
}

Those 3 classes are mapped to 3 tables with entity framework. Each of them has a column « Id » (Table per type). So far, this is working well.

The problem is that a Student can also be a Teacher. When I try to get both the Student and the Teacher objects in the same DbContext, I get the error :

All objects in the EntitySet 'Context.People' must have unique primary keys. However, an instance of type 'Student' and an instance of type Teacher' both have the same primary key value.

Is there a way to work around this problem ?

EDIT : Here's more details about my code :

using(var context = new CoreContext())
{
    var testStudents = context.Students.ToList();
    var testTeachers = context.Teachers.ToList();
}

(Error happens when context.Teachers.ToList() is called).

public class CoreContext : DbContext
{
    public DbSet<Student> Students { get; set; }
    public DbSet<Teacher> Teachers { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
         modelBuilder.Configurations.Add(new PersonMap());
         modelBuilder.Configurations.Add(new StudentMap());
         modelBuilder.Configurations.Add(new TeacherMap());
    }
}

internal class PersonMap: EntityTypeConfiguration<Person>
{
    public PersonMap() 
    {
        this.HasKey(i => i.Id);
        this.Property(i => i.Id).HasColumnName("Id");
        this.Property(i => i.Name).HasColumnName("Name");
        this.ToTable("People");
    }
}

internal class StudentMap : EntityTypeConfiguration<Student>
{
    public StudentMap() 
    {
        this.ToTable("Students");
    }
}

internal class TeacherMap : EntityTypeConfiguration<Teacher>
{
    public TeacherMap() 
    {
        this.ToTable("Teachers");
    }
}

Upvotes: 1

Views: 2218

Answers (2)

Hussein Bilal
Hussein Bilal

Reputation: 26

you may need to specify a little more like that

public Abstract class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}



public class CoreContext : DbContext
{
    public DbSet<Person> Person { get; set; }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
         modelBuilder.Configurations.Add(new PersonMap());
         modelBuilder.Configurations.Add(new StudentMap());
         modelBuilder.Configurations.Add(new TeacherMap());
    }
}




var testStudents = context.Person.OfType<Students>().ToList();
 var testTeachers = context.Person.OfType<Teacher>().ToList();

Upvotes: 0

JotaBe
JotaBe

Reputation: 39045

This can only happen if your DB contains a row in the People table that is joined both to Student and Teacher tables. To discover this offending row (or rows) run this query in your database:

Select P.Id 
from People P
left join Students S on P.Id = S.Id
left join Teachers T on P.Id = T.Id
where S.Id is not null and T.Id is not null

If this query returns entries, they must have been created directly in the DB. EF can't have done it.

Explanation: with your inheritance hierarchy, a person (row of People) can either be a Student or a Teacher but not both at the same time. However, there is nothing in the satabase that avoids this to happen. It must have been created directly in the DB as test data, or it was created with a different inheritance hierarchy, which was later changed.

Upvotes: 1

Related Questions