我重命名了几个实体及其导航属性,并在EF 5中生成了一个新的迁移。通常在EF迁移中重命名,默认情况下它会删除对象并重新创建它们。这不是我想要的,所以我几乎不得不从头开始构建迁移文件。
public override void Up()
{
DropForeignKey("dbo.ReportSectionGroups", "Report_Id", "dbo.Reports");
DropForeignKey("dbo.ReportSections", "Group_Id", "dbo.ReportSectionGroups");
DropForeignKey("dbo.Editables", "Section_Id", "dbo.ReportSections");
DropIndex("dbo.ReportSectionGroups", new[] { "Report_Id" });
DropIndex("dbo.ReportSections", new[] { "Group_Id" });
DropIndex("dbo.Editables", new[] { "Section_Id" });
RenameTable("dbo.ReportSections", "dbo.ReportPages");
RenameTable("dbo.ReportSectionGroups", "dbo.ReportSections");
RenameColumn("dbo.ReportPages", "Group_Id", "Section_Id");
AddForeignKey("dbo.ReportSections", "Report_Id", "dbo.Reports", "Id");
AddForeignKey("dbo.ReportPages", "Section_Id", "dbo.ReportSections", "Id");
AddForeignKey("dbo.Editables", "Page_Id", "dbo.ReportPages", "Id");
CreateIndex("dbo.ReportSections", "Report_Id");
CreateIndex("dbo.ReportPages", "Section_Id");
CreateIndex("dbo.Editables", "Page_Id");
}
public override void Down()
{
DropIndex("dbo.Editables", "Page_Id");
DropIndex("dbo.ReportPages", "Section_Id");
DropIndex("dbo.ReportSections", "Report_Id");
DropForeignKey("dbo.Editables", "Page_Id", "dbo.ReportPages");
DropForeignKey("dbo.ReportPages", "Section_Id", "dbo.ReportSections");
DropForeignKey("dbo.ReportSections", "Report_Id", "dbo.Reports");
RenameColumn("dbo.ReportPages", "Section_Id", "Group_Id");
RenameTable("dbo.ReportSections", "dbo.ReportSectionGroups");
RenameTable("dbo.ReportPages", "dbo.ReportSections");
CreateIndex("dbo.Editables", "Section_Id");
CreateIndex("dbo.ReportSections", "Group_Id");
CreateIndex("dbo.ReportSectionGroups", "Report_Id");
AddForeignKey("dbo.Editables", "Section_Id", "dbo.ReportSections", "Id");
AddForeignKey("dbo.ReportSections", "Group_Id", "dbo.ReportSectionGroups", "Id");
AddForeignKey("dbo.ReportSectionGroups", "Report_Id", "dbo.Reports", "Id");
}
我所要做的就是将dbo.ReportSections
重命名为dbo.ReportPages
,然后将dbo.ReportSectionGroups
重命名为dbo.ReportSections
。然后我需要将dbo.ReportPages
上的外键列从Group_Id
重命名为Section_Id
。
我正在删除将表连接在一起的外键和索引,然后我重命名表和外键列,然后我再次添加索引和外键。我以为这会起作用,但我收到一个SQL错误。
消息15248,级别11,状态1,过程sp_rename,行215参数@objname不明确或声明的@objtype(COLUMN)错误。消息4902,级别16,状态1,行10无法找到对象“dbo.ReportSections”,因为它不存在或您没有权限。
我不是很容易弄清楚这里有什么问题。任何见解都会非常有帮助。
没关系。我这样做比实际需要的更复杂。
这就是我所需要的一切。重命名方法只是生成对sp_rename系统存储过程的调用,我想这会处理所有事情,包括具有新列名的外键。
public override void Up()
{
RenameTable("ReportSections", "ReportPages");
RenameTable("ReportSectionGroups", "ReportSections");
RenameColumn("ReportPages", "Group_Id", "Section_Id");
}
public override void Down()
{
RenameColumn("ReportPages", "Section_Id", "Group_Id");
RenameTable("ReportSections", "ReportSectionGroups");
RenameTable("ReportPages", "ReportSections");
}
如果您不喜欢手动编写/更改Migration类中所需的代码,可以按照两步方法自动生成所需的RenameColumn
代码:
第一步使用ColumnAttribute
引入新的列名,然后添加迁移(例如Add-Migration ColumnChanged
)
public class ReportPages
{
[Column("Section_Id")] //Section_Id
public int Group_Id{get;set}
}
第二步更改属性名称,并再次应用于程序包管理器控制台中的相同迁移(例如Add-Migration ColumnChanged -force
)
public class ReportPages
{
[Column("Section_Id")] //Section_Id
public int Section_Id{get;set}
}
如果查看Migration类,可以看到生成的自动代码是RenameColumn
。
为了扩展Hossein Narimani Rad的答案,您可以分别使用System.ComponentModel.DataAnnotations.Schema.TableAttribute和System.ComponentModel.DataAnnotations.Schema.ColumnAttribute重命名表和列。
这有几个好处:
例如,添加[Table("Staffs")]
:
[Table("Staffs")]
public class AccountUser
{
public long Id { get; set; }
public long AccountId { get; set; }
public string ApplicationUserId { get; set; }
public virtual Account Account { get; set; }
public virtual ApplicationUser User { get; set; }
}
将生成迁移:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_AccountUsers_Accounts_AccountId",
table: "AccountUsers");
migrationBuilder.DropForeignKey(
name: "FK_AccountUsers_AspNetUsers_ApplicationUserId",
table: "AccountUsers");
migrationBuilder.DropPrimaryKey(
name: "PK_AccountUsers",
table: "AccountUsers");
migrationBuilder.RenameTable(
name: "AccountUsers",
newName: "Staffs");
migrationBuilder.RenameIndex(
name: "IX_AccountUsers_ApplicationUserId",
table: "Staffs",
newName: "IX_Staffs_ApplicationUserId");
migrationBuilder.RenameIndex(
name: "IX_AccountUsers_AccountId",
table: "Staffs",
newName: "IX_Staffs_AccountId");
migrationBuilder.AddPrimaryKey(
name: "PK_Staffs",
table: "Staffs",
column: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Staffs_Accounts_AccountId",
table: "Staffs",
column: "AccountId",
principalTable: "Accounts",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Staffs_AspNetUsers_ApplicationUserId",
table: "Staffs",
column: "ApplicationUserId",
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Staffs_Accounts_AccountId",
table: "Staffs");
migrationBuilder.DropForeignKey(
name: "FK_Staffs_AspNetUsers_ApplicationUserId",
table: "Staffs");
migrationBuilder.DropPrimaryKey(
name: "PK_Staffs",
table: "Staffs");
migrationBuilder.RenameTable(
name: "Staffs",
newName: "AccountUsers");
migrationBuilder.RenameIndex(
name: "IX_Staffs_ApplicationUserId",
table: "AccountUsers",
newName: "IX_AccountUsers_ApplicationUserId");
migrationBuilder.RenameIndex(
name: "IX_Staffs_AccountId",
table: "AccountUsers",
newName: "IX_AccountUsers_AccountId");
migrationBuilder.AddPrimaryKey(
name: "PK_AccountUsers",
table: "AccountUsers",
column: "Id");
migrationBuilder.AddForeignKey(
name: "FK_AccountUsers_Accounts_AccountId",
table: "AccountUsers",
column: "AccountId",
principalTable: "Accounts",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_AccountUsers_AspNetUsers_ApplicationUserId",
table: "AccountUsers",
column: "ApplicationUserId",
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
在EF Core(2.0)中,我使用以下语句重命名表和列:
至于重命名表:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameTable(name: "OldTableName", schema: "dbo", newName: "NewTableName", newSchema: "dbo");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameTable(name: "NewTableName", schema: "dbo", newName: "OldTableName", newSchema: "dbo");
}
至于重命名列:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(name: "OldColumnName", table: "TableName", newName: "NewColumnName", schema: "dbo");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(name: "NewColumnName", table: "TableName", newName: "OldColumnName", schema: "dbo");
}
我在EF6(代码第一实体重命名)中尝试了相同的操作。我只是重命名了类并使用包管理器控制台添加了迁移,并且自动为我生成了使用RenameTable(...)的迁移。我必须承认,我确保对实体的唯一更改是重命名它所以没有新列或重命名列,所以我不能确定这是EF6的东西还是只是EF(总是)能够检测到这种简单的迁移。
表名和列名可以指定为DbContext
映射的一部分。然后在迁移中不需要这样做。
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Restaurant>()
.HasMany(p => p.Cuisines)
.WithMany(r => r.Restaurants)
.Map(mc =>
{
mc.MapLeftKey("RestaurantId");
mc.MapRightKey("CuisineId");
mc.ToTable("RestaurantCuisines");
});
}
}