Search code examples
c#.net-core.net-core-3.0entity-framework-core-3.0

Seeding Related Data in EF Core 3, getting error: Object reference not set to an instance of an object


I followed the data seeding process explained on https://learn.microsoft.com/en-us/ef/core/modeling/data-seeding.

Used "Model seed data" method to seed related data as follows:

public class CaseType
{
    public int CaseTypeId { get; set; }
    [Required]
    public string Name { get; set; }

    public ICollection<Case> Cases { get; set; }
}

public class Case
{
    public int CaseId { get; set; }
    [Required]
    public string Name { get; set; }
    public string Description { get; set; }

    public CaseType CaseType { get; set; }

    public int CaseTypeId { get; set; }
}

public class ApplicationDbContext : ApiAuthorizationDbContext<ApplicationUser>
{
    public DbSet<CaseType> CaseTypes { get; set; }
    public DbSet<Case> Cases { get; set; }

    public ApplicationDbContext(
        DbContextOptions options,
        IOptions<OperationalStoreOptions> operationalStoreOptions) : base(options, operationalStoreOptions)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder) {

        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<CaseType>().HasData(
            new CaseType {
                CaseTypeId  = 1,
                Name        = "Case Type 1",
            }
        );

        modelBuilder.Entity<Case>().HasData(
            new Case {
                CaseId      = 1,
                CaseTypeId  = 1,
                Name        = "Case 1",
                Description = "Case 1 Description",

            }
        );
    }
}

And gets following error when I run command: dotnet ef migrations add SeedDatabase

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 3.0.0-preview5.19227.1 initialized 'ApplicationDbContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: None
System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.EntityFrameworkCore.Update.Internal.SharedTableEntryMap`1.GetMainEntry(IUpdateEntry entry)
   at Microsoft.EntityFrameworkCore.Update.Internal.SharedTableEntryMap`1.GetOrAddValue(IUpdateEntry entry)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.DiffData(TableMapping source, TableMapping target, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Diff(TableMapping source, TableMapping target, DiffContext diffContext)+MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.DiffCollection[T](IEnumerable`1 sources, IEnumerable`1 targets, DiffContext diffContext, Func`4 diff, Func`3 add, Func`3 remove, Func`4[] predicates)+MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Sort(IEnumerable`1 operations, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Object reference not set to an instance of an object.

When I commented out "CaseTypeId = 1" as shown below. Data inserted and CaseTypeId field in Cases table has value "null"

        modelBuilder.Entity<Case>().HasData(
            new Case {
                CaseId      = 1,
                //CaseTypeId  = 1,
                Name        = "Case 1",
                Description = "Case 1 Description",

            }
        );

Problem is with foreign key property "CaseTypeId" in Case Entity.

So what am I doing wrong here ?


Solution

  • The error is of course not user friendly. But this is preview (beta) software, so it is not expected to work perfectly. In fact I was not able to reproduce it with 3.0.0-preview6, but then of course the update database failed with invalid foreign key reference error.

    EF Core Model seed data has several requirements. First, you have to specify PK and FK values explicitly. Second (which is causing your issue), you have to seed both primary and related data.

    Thus seeding the CaseTypes with the PKs needed for seeding the Case FKs should solve the problem, e.g.

    modelBuilder.Entity<CaseType>().HasData(
        new CaseType
        {
            CaseTypeId = 1, // <--
            Name = "Case Type 1",
        }
    );
    
    modelBuilder.Entity<Case>().HasData(
        new Case
        {
            CaseId = 1,
            CaseTypeId = 1, // <--
            Name = "Case 1",
            Description = "Case 1 Description",
        },
        new Case
        {
            CaseId = 2,
            CaseTypeId = 1, // <--
            Name = "Case 2",
            Description = "Case 2 Description",
        }
    );