Search code examples
c#entity-frameworkentity-framework-coredatabase-migrationseeding

EFCore data seeding missing data insertion?


I have two related classes as follows:

public class Student
{
    public long Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public long FavoriteCourseId { get; set; }
}

public class Course
{
    public long Id { get; set; }
    public string Name { get; set; }
}

There is one to one relationship between the two. Student has a foreign key which references the Course via the FavoriteCourseId.

My fluent mappings are as follows:

protected override void OnModelCreating(ModelBuilder modelBuilder) {
  modelBuilder.Entity<Student>(entity => {
    entity.ToTable("Student").HasKey(k => k.Id);
    entity.Property(p => p.Id).HasColumnName("StudentID");
    entity.Property(p => p.Name).IsRequired();
    entity.Property(p => p.Email).IsRequired();
    entity.Property(p => p.FavoriteCourseId).IsRequired();
  });

  modelBuilder.Entity<Course>(entity => {
    entity.ToTable("Course").HasKey(k => k.Id);
    entity.Property(p => p.Id).HasColumnName("CourseID");
    entity.Property(p => p.Name).IsRequired();
  });

  modelBuilder.Entity<Student>()
            .HasOne(typeof(Course))
            .WithOne()
            .HasForeignKey("Student", "FavoriteCourseId")
            .HasConstraintName("FK_Student_Course");

  modelBuilder.Entity<Course>().HasData(
            new Course { Id = 1, Name = "Calculus" },
            new Course { Id = 2, Name = "Chemistry" },
            new Course { Id = 3, Name = "Literature" },
            new Course { Id = 4, Name = "Trigonometry" },
            new Course { Id = 5, Name = "Microeconomics" });

  modelBuilder.Entity<Student>().HasData(
     new Student { Id = 1, Name = "Alice", Email = "alice@gmail.com", FavoriteCourseId = 2 },
     new Student { Id = 2, Name = "Bob", Email = "bob@outlook.com", FavoriteCourseId = 2 });
}

Here, I am seeding two Students - Alice and Bob. However, when I create the init migration then the migration seeds only Bob and ignores Alice.

migrationBuilder.InsertData(
            table: "Student",
            columns: new[] { "StudentID", "Email", "FavoriteCourseId", "Name" },
            values: new object[] { 2L, "bob@outlook.com", 2L, "Bob" });

Why is the data row for Alice being ignored? I also noticed that the data row only gets ignored when FavoriteCourseId is same for both Alice and Bob. If I change the FavoriteCourseId to different values for both rows then Alice gets inserted.


Solution

  • It seeds only one student because according your model the same course can only have one student. Change the model to this:

    public class Student
    {
       [Key]
        public long Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public long FavoriteCourseId { get; set; }
        [ForeignKey(nameof(FavoriteCourseId ))]
         [InverseProperty("FavoriteCourses")]
          public virtual Course FavoriteCourse { get; set; }
    }
    
    public class Course
    {
        [Key]
        public long Id { get; set; }
        public string Name { get; set; }
        [InverseProperty(nameof(Student.FavoriteCourse))]
        public virtual ICollection<Student> Students{ get; set; }
    }
    
    

    and the dbcontext:

    modelBuilder.Entity<Student>(entity =>
    {
     entity.HasOne(d => d.FavoriteCourse)
     .WithMany(p => p.Courses)
     .HasForeignKey(d => d.FavoriteCourseId)
      .OnDelete(DeleteBehavior.ClientSetNull);
    }
    
    modelBuilder.Entity<Course>().HasData(
                new Course { Id = 1, Name = "Calculus" },
                new Course { Id = 2, Name = "Chemistry" },
                new Course { Id = 3, Name = "Literature" },
                new Course { Id = 4, Name = "Trigonometry" },
                new Course { Id = 5, Name = "Microeconomics" });
    
      modelBuilder.Entity<Student>().HasData(
         new Student { Id = 1, Name = "Alice", Email = "alice@gmail.com", FavoriteCourseId = 2 },
         new Student { Id = 2, Name = "Bob", Email = "bob@outlook.com", FavoriteCourseId = 2 });