I am writing an ASP.NET Core API using Entity Framework with a code-first approach. I'm using 2 model classes with a one-to-many relation. Generating the migrations for the models goes perfectly fine, but as soon as the models are being seeded, I get an error.
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; }
}
Database context:
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());
}
}
Error message:
The seed entity for entity type 'Level' with the key value 'Id:1' cannot be added because it has the navigation 'LevelTasks' set. To seed relationships you need to add the related entity seed to 'LevelTask' and specify the foreign key values {'LevelId'}.
I understand there is a foreign key missing but after reading tons of documentation and forums and trying all different answer still no result.
Do you guys have any idea's what I am doing wrong?
As explained on msdn :
To add entities that have a relationship the foreign key values need to be specified
In your example, you assume that they'll be created because of the DatabaseGenerated(DatabaseGeneratedOption.Identity)
attribute. Unfortunately, if you want to seed data in OnModelCreating
method, you have to specify them. Below is non-elegant yet working example of how you should seed your data in:
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
});
}
}
}
If you really want to ignore the Ids, you can seed your data with custom logic as detailed here .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.