.NET核心实体框架种子数据关系



我正在使用实体框架和代码优先的方法编写一个ASP.NET核心API。我使用了两个具有一对多关系的模型类。为模型生成迁移非常顺利,但一旦模型被播种,我就会收到一个错误。

public class Level
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int Number { get; set; }
public List<LevelTask> LevelTasks { get; set; }
}
public class LevelTask
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Text { get; set; }
public int Number { get; set; }
public Level Level { get; set; }
}

数据库上下文:

public class VoutlosContext : DbContext
{
public VoutlosContext(DbContextOptions<VoutlosContext> options)
: base(options)
{
}
// Database tables
public DbSet<Level> Levels { get; set; }
public DbSet<LevelTask> LevelTasks { get; set; }
// Setup testing data
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Level>()
.HasMany<LevelTask>(l => l.LevelTasks)
.WithOne(lt => lt.Level);

var levels = Builder<Level>.CreateListOfSize(50).All()
.With(l => l.Number = 1)
.With(l => l.LevelTasks = Builder<LevelTask>.CreateListOfSize(10).All()
.With(lt => lt.Number = 1)
.With(lt => lt.Text = Faker.Lorem.Sentence())
.Build().ToList())
.Build();
modelBuilder.Entity<Level>().HasData(levels.ToArray());

}
}

错误消息:

无法添加键值为"Id:1"的实体类型"Level"的种子实体,因为它设置了导航"LevelTasks"。若要为关系设定种子,您需要将相关实体种子添加到"LevelTask",并指定外键值{"LevelId"}。

我知道缺少一个外键,但在阅读了大量文档和论坛并尝试了所有不同的答案后,仍然没有结果。

你们知道我做错了什么吗?

如msdn:所述

若要添加具有外键值所需关系的实体待指定

在您的示例中,您假设它们是由于DatabaseGenerated(DatabaseGeneratedOption.Identity)属性而创建的。不幸的是,如果要在OnModelCreating方法中为数据种子,则必须指定它们。以下是关于如何在中播种数据的非优雅但有效的示例

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Level>()
.HasMany<LevelTask>(l => l.LevelTasks)
.WithOne(lt => lt.Level);
int levelTaskIdCounter = 1;
for (int j = 1; j <= 50; j++)
{
modelBuilder.Entity<Level>().HasData(
new Level
{
Id = j,
Number = 1
});
for (int i = 1; i <= 10; i++)
{
modelBuilder.Entity<LevelTask>().HasData(
new
{
Id = levelTaskIdCounter++,
Number = 1,
// Note that I'm specifying the shadow property used 
// to create the relationship here. That's possible 
//  thanks to anonymous classes
LevelId = j
});
}
}
}

如果你真的想忽略Id,你可以用这里详细介绍的自定义逻辑为你的数据播种。

最新更新