微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

EF Core 模型种子数据在键名中强加复数形式

如何解决EF Core 模型种子数据在键名中强加复数形式

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

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

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

TagPost 类具有相应的 TagPost 表,带有 TagIdPostId 主键(注意单数 命名约定)

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

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

当我添加 try 到 add-migration Initial 时,阻塞错误会中断迁移创建:

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

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

我看到它通过复数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,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 表名?

解决方法

正如错误消息中所写,如果您想使用多对多,您应该在两个表中都有主键:

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 }));
    
}
,

当 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 });
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。