Search code examples
c#entity-frameworkentity-framework-migrationsjunction-table

EF Code First Migration insists on switching junction table names


I have an EF Code First model containing a table for Foo and a table for Bar. This is a many to many relationship so EF generated a junction table called FooBars:

CreateTable(
    "dbo.FooBar",
    c => new
        {
            Foo_Id = c.Int(nullable: false),
            Bar_Id = c.Int(nullable: false),
        })
    .PrimaryKey(t => new { t.Foo_Id, t.Bar_Id })
    .ForeignKey("dbo.Foos", t => t.Foo_Id, cascadeDelete: true)
    .ForeignKey("dbo.Bars", t => t.Bar_Id, cascadeDelete: true)             
    .Index(t => t.Foo_Id)
    .Index(t => t.Bar_Id);

All fine. Now, I made some changes to the model and added a migration. The Foo entity now has some extra string and int properties, no changes in relations or anything. However, for some reason, EF now insists that the junction table should be called BarFoos, and wants to delete the original FooBars table:

 DropForeignKey("dbo.FooBars", "Foo_Id", "dbo.Foos");
 DropForeignKey("dbo.FooBars", "Bar_Id", "dbo.Bars");
 DropIndex("dbo.Foobars", new[] { "Foo_Id" });
 DropIndex("dbo.FooBars", new[] { "Bar_Id" });

 CreateTable(
      "dbo.BarFoos",
           c => new
                {
                    Bar_Id = c.Int(nullable: false),
                    Foo_Id = c.Int(nullable: false),
                })
 .PrimaryKey(t => new { t.Bar_Id, t.Foo_Id })
 .ForeignKey("dbo.Bars", t => t.Bar_Id, cascadeDelete: true)
 .ForeignKey("dbo.Foos", t => t.Foo_Id, cascadeDelete: true)
 .Index(t => t.Bar_Id)
 .Index(t => t.Foo_Id);

 DropTable("dbo.FooBars");

Obviously I could just copy all records from FooBars into BarFoos, but that's annoying as hell, and something I'll need to keep doing as I make changes to the model and re-generate this particular migration. Why is EF insisting that the junction table should suddenly be the other way around? Can I do something to avoid this?


Solution

  • I've had this happen previously - I never did find a solution but my workaround was to force the table name in Fluent API. e.g:

    modelBuilder.Entity(Of User)() _ 
    .HasMany(Function(u) u.Roles) _ 
    .WithMany(Function(r) r.Users) _ 
    .Map(Function(u) u.MapRightKey("Role_RoleID").MapLeftKey("User_UserID").ToTable("UserRoles"))
    

    (C#, to match the question language):

    modelBuilder.Entity<User>()
    .HasMany(u => u.Roles)
    .WithMany(r => r.Users)
    .Map(u => u.MapRightKey("Role_RoleID").MapLeftKey("User_UserID").ToTable("UserRoles"));