【问题标题】:EF Core Model Seed Data imposes plurals in the key namesEF Core 模型种子数据在键名中强加复数
【发布时间】:2021-02-06 16:27:00
【问题描述】:

我有 TagPost 类(多对多关系,代码优先)

class Post {
    ICollection<Tag> Tags {get; set;} = new List<Tag>();
}

class Tag {
    ICollection<Post> Posts {get; set;} = new List<Post>();
}

TagPost 类具有对应的 TagPost 表和 TagIdPostId 主键(注意 singular 命名约定)

在配置我的Post 的构建器时,我说

builder
    .HasMany(p => p.Tags)
    .WithMany(p => p.Posts)
    .UsingEntity(j => j.HasData(new { PostId = 1, TagId = 1 }));

当我向add-migration Initial 添加尝试时,一个阻塞错误会中断迁移创建:

实体类型 'PostTag (Dictionary)',因为没有为 必需的属性“PostsId”。

有人能解释一下这条消息背后隐藏着什么吗?

我看到它通过 plurals (PostsId vs PostId),但我不想在外键上使用复数,有没有办法使用 PostId而不是PostsId?

.UsingEntity(j => j.HasData(new { PostsId = 1, TagsId = 1 }));

此外,它还会创建以下迁移:

migrationBuilder.CreateTable(
    name: "PostTag (Dictionary<string, object>)",
    columns: table => new
    {
        PostsId = table.Column<int>(type: "int", nullable: false),
        TagsId = table.Column<int>(type: "int", nullable: false)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_PostTag (Dictionary<string, object>)", x => new { x.PostsId, x.TagsId });
        table.ForeignKey(
            name: "FK_PostTag (Dictionary<string, object>)_Post_PostsId",
            column: x => x.PostsId,
            principalTable: "Post",
            principalColumn: "PostId",
            onDelete: ReferentialAction.Cascade);

表名“PostTag (Dictionary)”(太恐怖了)还有 PrimaryKey("PK_PostTag (Dictionary)" ...

使用这些约定的逻辑是什么?怎样才能有正常的PostTag 表名?

【问题讨论】:

  • 想从选民那里结束这个问题,什么“堆栈溢出指南”不符合这个问题......
  • 我之前没有使用过 UsingEntity。我通常在模型中显式地创建连接表。但是,您确定要在该配置中使用 HasData 而不是 HasKey?

标签: c# entity-framework-core ef-code-first ef-core-5.0


【解决方案1】:

因为它写在错误消息中,如果你想使用多对多,你应该在两个表中都有主键:

public class Post
{
     [Key]
    public int PostId { get; set; }
    public ICollection<Tag> Tags { get; set; }
}

public class Tag
{
    [Key]
    public int TagId { get; set; }
    public ICollection<Post> Posts { get; set; }
}

和数据库上下文:

 protected override void OnModelCreating(ModelBuilder modelBuilder)
{

    var posts = new[]
     {
     new Post{PostId=1},
     new Post{PostId=2},
     new Post{PostId=3}
    };

 var tags = new[]
    {
     new Tag{TagId=1},
     new Tag{TagId=2}
    };

 modelBuilder.Entity<Tag>().HasData(tags);

   modelBuilder.Entity<Post>().HasData(posts);

    modelBuilder.Entity<Post>()
    .HasMany(p => p.Tags)
     .WithMany(p => p.Posts)
    .UsingEntity(j => j.HasData(new { PostsPostId = 1, TagsTagId = 1 }));
    
}

【讨论】:

    【解决方案2】:

    当 EF 为您生成某些内容时,它会遵循其特定的命名约定。 PostTag 是 EF 生成的连接表,用于维护多对多关系,你不应该知道它的存在以及 EF 是如何管理它的。

    如果您确实想了解该表并希望它的列以您的方式命名,那么您必须创建连接实体,根据您的需要命名属性并显式配置它。

    加入实体 -

    public class PostTag
    {
        public int PostId { get; set; }
        public int TagId { get; set; }
    
        public Post Post { get; set; }
        public Tag Tag { get; set; }
    }
    

    配置,连同种子 -

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>(e =>
        {
            e.ToTable("Post").HasData(new Post { Id = 1, Title = "EF Deep Dive" });               
            e.HasMany(p => p.Tags)
            .WithMany(p => p.Posts)
            .UsingEntity<PostTag>(
                link => link.HasOne(p => p.Tag).WithMany().HasForeignKey(p => p.TagId),
                link => link.HasOne(p => p.Post).WithMany().HasForeignKey(p => p.PostId))
            .HasKey(p => new { p.PostId, p.TagId });
        });
    
        modelBuilder.Entity<Tag>(e =>
        {
            e.ToTable("Tag").HasData(new Tag { Id = 1, Name = "EF" }, new Tag { Id = 2, Name = ".NET" });
        });
    
        modelBuilder.Entity<PostTag>().HasData(new { PostId = 1, TagId = 1 });
    }
    

    【讨论】:

      猜你喜欢
      • 2020-12-13
      • 2019-02-17
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 2021-04-26
      • 2017-06-23
      • 1970-01-01
      • 2020-10-20
      相关资源
      最近更新 更多