【问题标题】:.NET Core Entity Framework seeding data relations.NET Core Entity Framework 播种数据关系
【发布时间】:2020-11-28 01:58:01
【问题描述】:

我正在使用 Entity Framework 和代码优先的方法编写一个 ASP.NET Core API。我正在使用 2 个具有一对多关系的模型类。为模型生成迁移非常顺利,但是一旦为模型播种,就会出现错误。

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”的种子实体,因为它设置了导航“LevelTask​​s”。要为关系播种,您需要将相关实体种子添加到“LevelTask​​”并指定外键值 {'LevelId'}。

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

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

【问题讨论】:

  • 不确定,但您可能想看看这个answer

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


【解决方案1】:

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,可以使用自定义逻辑为您的数据播种,详见 here

【讨论】:

    猜你喜欢
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 2016-05-14
    • 1970-01-01
    • 2022-08-02
    • 2020-02-24
    相关资源
    最近更新 更多