简体   繁体   中英

.NET Core Entity Framework seeding data relations

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM