在EF Core 3中播种相关数据,出现错误:对象引用未设置为对象的实例

时间:2019-07-13 05:08:02

标签: c# .net-core .net-core-3.0 entity-framework-core-3.0

我遵循了https://docs.microsoft.com/en-us/ef/core/modeling/data-seeding中说明的数据播种过程。

使用“模型种子数据”方法来播种相关数据,如下所示:

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",

            }
        );
    }
}

运行命令时出现以下错误:dotnet ef迁移添加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.

当我注释掉“ CaseTypeId = 1”时,如下所示。插入的数据和Cases表中的CaseTypeId字段的值为“ null”

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

            }
        );

问题与案例实体中的外键属性“ CaseTypeId”有关。

那我在做什么错了?

1 个答案:

答案 0 :(得分:3)

该错误当然不是用户友好的。但是,这是预览版(测试版)软件,因此不能正常使用。实际上,我无法使用3.0.0-preview6进行复制,但是当然更新数据库失败,并带有无效的外键引用错误。

EF核心https://tympanus.net/codrops/2019/04/24/how-to-build-an-underwater-style-navigation-using-pixijs/有几个要求。首先,您必须明确指定PK和FK值。其次(这是导致您出现问题的原因),您必须播种两者主要数据和相关数据。

因此,用CaseType个FK种子所需的PK种子来Case个种子应该可以解决该问题,例如

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