实体框架自动重命名多对多表而不进行任何更改

gri*_*n55 6 c# entity-framework ef-code-first ef-migrations

我在同一个项目工作了差不多一年半,今天当我想在数据库中添加一个更改(代码优先)时,所有突然的EF迁移都希望重命名很多存在于其中的多对多表.数据库今天.Theese表名称已经超过2年没有变化,我无法弄清楚为什么EF想要重命名它们.我已经检查了迁移所指向的实体文件,并且没有对可以解释此问题的文件进行更改.在这个项目中,我们使用数据注释,因此我们从未给多对多表赋予任何名称,我们只是让EF设置表的名称.任何帮助表示赞赏!

        RenameTable(name: "dbo.FilterLocation", newName: "LocationFilter");
        RenameTable(name: "dbo.FilterCluster", newName: "ClusterFilter");
        RenameTable(name: "dbo.ProfileFilter", newName: "FilterProfile");
        RenameTable(name: "dbo.HtmlTemplateFilterProfile", newName: "ProfileHtmlTemplateFilter");
        RenameTable(name: "dbo.HtmlTemplateProfile", newName: "ProfileHtmlTemplate");
        RenameTable(name: "dbo.CategoryHtmlTemplateFilter", newName: "HtmlTemplateFilterCategory");
        RenameTable(name: "dbo.HtmlTemplateCategory", newName: "CategoryHtmlTemplate");
        DropPrimaryKey("dbo.LocationFilter");
        DropPrimaryKey("dbo.ClusterFilter");
        DropPrimaryKey("dbo.FilterProfile");
        DropPrimaryKey("dbo.ProfileHtmlTemplateFilter");
        DropPrimaryKey("dbo.ProfileHtmlTemplate");
        DropPrimaryKey("dbo.HtmlTemplateFilterCategory");
        DropPrimaryKey("dbo.CategoryHtmlTemplate");
         AddPrimaryKey("dbo.LocationFilter", new[] { "Location_LocationId", "Filter_FilterId" });
        AddPrimaryKey("dbo.ClusterFilter", new[] { "Cluster_ClusterId", "Filter_FilterId" });
        AddPrimaryKey("dbo.FilterProfile", new[] { "Filter_FilterId", "Profile_ProfileId" });
        AddPrimaryKey("dbo.ProfileHtmlTemplateFilter", new[] { "Profile_ProfileId", "HtmlTemplateFilter_HtmlTemplateFilterId" });
        AddPrimaryKey("dbo.ProfileHtmlTemplate", new[] { "Profile_ProfileId", "HtmlTemplate_HtmlTemplateId" });
        AddPrimaryKey("dbo.HtmlTemplateFilterCategory", new[] { "HtmlTemplateFilter_HtmlTemplateFilterId", "Category_CategoryId" });
        AddPrimaryKey("dbo.CategoryHtmlTemplate", new[] { "Category_CategoryId", "HtmlTemplate_HtmlTemplateId" });
Run Code Online (Sandbox Code Playgroud)

*编辑我实际做的更改如下:

    AddColumn("dbo.HtmlAdField", "MediaFactConnection", c => c.Int(nullable: false));
    AddColumn("dbo.HtmlAd", "FactId", c => c.Int());
    CreateIndex("dbo.HtmlAd", "FactId");
    AddForeignKey("dbo.HtmlAd", "FactId", "dbo.Fact", "FactId");
    DropColumn("dbo.HtmlAdField", "ConnectionState");
Run Code Online (Sandbox Code Playgroud)

Nic*_*rce 8

对于绊倒这篇文章的任何人...

与我最初的评论相反,让迁移按生成方式运行无法解决我的问题。我了解了为什么会发生这种行为,如何解决它,并从一开始就学到了关于更明确地配置实体的课程。

为什么?

实体框架将根据其算法配置实体的顺序来命名和配置联结表。DbSet<>modelBuilder“定义”出现的顺序更改了联结表的左/右表。我无法确切确定这会/如何影响所生成的代码,但就我而言,这一切在易受打击的Resharper“代码清理”之后都变成了梨形。

怎么修

通过显式配置多对多映射,可以模仿EF生成首次创建表时的行为。

这篇文章使我步入正轨: 在实体框架中使用Fluent API创建多对多关系

就我而言,EF试图将RoleCategory表重命名为CategoryRole(并且失败)。这是我添加的内容:

modelBuilder.Entity<Role>()
     .HasMany(e => e.Categories)
     .WithMany(e => e.Roles)
         .Map(m =>
         {
             m.ToTable("RoleCategory");
         });
Run Code Online (Sandbox Code Playgroud)

笔记

配置“从”表名称中首先命名的实体。例如对于我的桌子,RoleCategory我这样做:

Entity<Role>.HasMany(e => e.Categories)
Run Code Online (Sandbox Code Playgroud)

Entity<Category>.HasMany(e => e.Roles)
Run Code Online (Sandbox Code Playgroud)

.WithMany(e => e.Roles)在另一侧添加一个显式名称,命名导航属性。

使用.Map()指定表名。就我而言,当我使用.MapLeftKey()和指定列名称时,链接后的帖子失败.MapRightKey()

本质上,我只需要不断修改定义并add-migration每次运行,直到对表的所有操作从生成的DbMigration文件中消失为止。

我的教训

显然,最佳实践是从一开始就明确配置所有多对多关系。就我而言,我对联结表中涉及的两个实体均未做任何更改。但是,对一个遥远的“表兄弟”实体的更改以及对DbContext的重新排序使我困惑了一段时间。

学过的知识。希望其他人也能找到帮助。

  • 这是正确的,应该是公认的答案。 (2认同)