Home > other >  EF Core 5 Migration Creating Table Twice With Different Name
EF Core 5 Migration Creating Table Twice With Different Name

Time:12-29

I am using Visual Studio Community 2022 (64-bit, Version 17.1.0 Preview 1.1), ASP .Net 5 Razor Pages (Non-MVC), EF Core 5 and SQL Server.

I have two classes, that have a many to many relationship.

Class 1 (Tag):

public class Tag
{
    [Key]
    public int Id { get; set; }

    [Required]
    [Display(Name = "Tag Description")]
    [StringLength(50, ErrorMessage = "Description cannot be longer than 50 characters.")]
    public string Description { get; set; }

    [Required]
    public string Narrative { get; set; }

    //Tags Have One Subject
    //Tag.SubjectId FK
    [ForeignKey("SubjectID")]
    public int SubjectId { get; set; }
    public Subject Subject { get; set; }

    //Tags Have One Or More Documents
    //(TagDocument Join Table)
    public List<TagDocument> TagDocuments { get; set; }

    //Tags Have One Or More Acronyms
    //TagAcronym Join Table
    public ICollection<Acronym> Acronyms { get; set; }
    public List<TagAcronym> TagAcronyms { get; set; }
}

Class 2 (Acronym):

 public class Acronym
 {
     [Key]
     public int Id { get; set; }

     [Required]
     [Display(Name = "Acronym")]
     [StringLength(50, ErrorMessage = "Acronym cannot be longer than 50 characters.")]
     public string Abbreviation { get; set; }

     [Required]
     [Display(Name = "Description")]
     [StringLength(100, ErrorMessage = "Description cannot be longer than 100 characters.")]
     public string Description { get; set; }

     [StringLength(250, ErrorMessage = "URL cannot be longer than 250 characters.")]
     public string URL { get; set; }

     //Acronyms Have One Or More AcronymOld
     //AcronymOld.AcronymId (FK)
     public List<AcronymOld> AcronymsOld { get; set; }

     //Acronyms Have One Or More Tags
     //TagAcronym Join Table
     public ICollection<Tag> Tags { get; set; }
     public List<TagAcronym> TagAcronyms { get; set; }
 }

Any Acronym can have many Tags, and a Tag can have many Acronyms.

I created a TagAcronym class to facilitate the creation of a Join Table in the database:

 public class TagAcronym
    {
        public int TagId { get; set; }
        public Tag Tag { get; set; }

        public int AcronymId { get; set; }
        public Acronym Acronym { get; set; }
    }
}

When I create the Migration it attempts to create a TagAcronym and an AcronymTag table for reasons I cannot understand.

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "AcronymTag",
        columns: table => new
        {
            AcronymsId = table.Column<int>(type: "int", nullable: false),
            TagsId = table.Column<int>(type: "int", nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_AcronymTag", x => new { x.AcronymsId, x.TagsId });
            table.ForeignKey(
                name: "FK_AcronymTag_Acronym_AcronymsId",
                column: x => x.AcronymsId,
                principalTable: "Acronym",
                principalColumn: "Id",
                onDelete: ReferentialAction.Cascade);
            table.ForeignKey(
                name: "FK_AcronymTag_Tag_TagsId",
                column: x => x.TagsId,
                principalTable: "Tag",
                principalColumn: "Id",
                onDelete: ReferentialAction.Cascade);
        });

    migrationBuilder.CreateTable(
        name: "TagAcronym",
        columns: table => new
        {
            TagId = table.Column<int>(type: "int", nullable: false),
            AcronymId = table.Column<int>(type: "int", nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_TagAcronym", x => new { x.TagId, x.AcronymId });
            table.ForeignKey(
                name: "FK_TagAcronym_Acronym_AcronymId",
                column: x => x.AcronymId,
                principalTable: "Acronym",
                principalColumn: "Id",
                onDelete: ReferentialAction.Cascade);
            table.ForeignKey(
                name: "FK_TagAcronym_Tag_TagId",
                column: x => x.TagId,
                principalTable: "Tag",
                principalColumn: "Id",
                onDelete: ReferentialAction.Cascade);
        });

    migrationBuilder.CreateIndex(
        name: "IX_AcronymTag_TagsId",
        table: "AcronymTag",
        column: "TagsId");

    migrationBuilder.CreateIndex(
        name: "IX_TagAcronym_AcronymId",
        table: "TagAcronym",
        column: "AcronymId");
}

Any help is appreciated. Thanks.

CodePudding user response:

you can use this model design :

public class Tag
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [Display(Name = "Tag Description")]
        [StringLength(50, ErrorMessage = "Description cannot be longer than 50 characters.")]
        public string Description { get; set; }

        [Required]
        public string Narrative { get; set; }

        //Tags Have One Subject
        //Tag.SubjectId FK
        [ForeignKey("SubjectID")]
        public int SubjectId { get; set; }
        public Subject Subject { get; set; }

        //Tags Have One Or More Documents
        //(TagDocument Join Table)
        public List<TagDocument> TagDocuments { get; set; }

        //Tags Have One Or More Acronyms
        //TagAcronym Join Table
        public List<TagAcronym> TagAcronyms { get; set; }
    }

public class Acronym
    {
        [Key]
        public int Id { get; set; }

        [Required]
        [Display(Name = "Acronym")]
        [StringLength(50, ErrorMessage = "Acronym cannot be longer than 50 characters.")]
        public string Abbreviation { get; set; }

        [Required]
        [Display(Name = "Description")]
        [StringLength(100, ErrorMessage = "Description cannot be longer than 100 characters.")]
        public string Description { get; set; }

        [StringLength(250, ErrorMessage = "URL cannot be longer than 250 characters.")]
        public string URL { get; set; }

        //Acronyms Have One Or More AcronymOld
        //AcronymOld.AcronymId (FK)
        public List<AcronymOld> AcronymsOld { get; set; }

        //Acronyms Have One Or More Tags
        //TagAcronym Join Table
        
        public List<TagAcronym> TagAcronyms { get; set; }
    }

datacontext

protected override void OnModelCreating(ModelBuilder modelBuilder) {
            //Tag and Subject one-to-one
            modelBuilder.Entity<Subject>()
                .HasOne(b => b.Tag)
                .WithOne(i => i.Subject)
                .HasForeignKey<Tag>(b => b.SubjectId);
            //Tag and TagDocument one-to-many
            modelBuilder.Entity<Tag>()
                .HasMany(t => t.TagDocuments)
                .WithOne(g => g.Tag)
                .HasForeignKey(g => g.TagId);
            //Acronym and AcronymsOld one-to-many
            modelBuilder.Entity<Acronym>()
                .HasMany(t => t.AcronymsOld)
                .WithOne(g => g.Acronym)
                .HasForeignKey(g => g.AcronymId);

            //Acronym and Tag many-to-many
            modelBuilder.Entity<TagAcronym>()
            .HasKey(t => new { t.TagId, t.AcronymId });

            modelBuilder.Entity<TagAcronym>()
                .HasOne(pt => pt.Tag)
                .WithMany(p => p.TagAcronyms)
                .HasForeignKey(pt => pt.TagId);

            modelBuilder.Entity<TagAcronym>()
                .HasOne(pt => pt.Acronym)
                .WithMany(t => t.TagAcronyms)
                .HasForeignKey(pt => pt.AcronymId);

        }

enter image description here

You can refer to the official document:https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api,fluent-api-simple-key,simple-key#many-to-many

CodePudding user response:

The relationship between Tag and Acronym are many to many so EF will automatically create a mapper table for these tables with name (TagAcronym or AcronymTag) so you dont need to explicitly specify TagAcroymn table.

  • Related