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



我遵循了 https://learn.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 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.

当我注释掉"CaseTypeId = 1"时,如下所示。插入的数据和案例表中的案例类型 ID 字段的值为"空">

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

问题出在案例实体中的外键属性"案例类型 ID"。

那么我在这里做错了什么?

该错误当然不是用户友好的。但这是预览版(测试版(软件,因此预计不会完美运行。事实上,我无法使用 3.0.0-preview6 重现它,但当然更新数据库失败了,出现无效的外键引用错误。

EF Core 模型种子数据有几个要求。首先,必须显式指定 PK 和 FK 值。其次(导致您的问题(,您必须为主要数据和相关数据设定种子。

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

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

最新更新