我重命名了几个实体及其导航属性,并在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错误。
Msg 15248,Level 11,State 1,Procedure sp_rename,215行 参数@objname是不明确的,或者声明的@objtype(COLUMN)是错误的。 Msg 4902,Level 16,State 1,Line 10 无法找到对象“dbo.ReportSections”,因为它不存在或您没有权限。
我很难搞清楚这里有什么问题。任何见解都会非常有用。
答案 0 :(得分:124)
没关系。我这样做比实际需要的更复杂。
这就是我所需要的一切。重命名方法只是生成对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");
}
答案 1 :(得分:31)
如果您不喜欢手动编写/更改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
。
答案 2 :(得分:10)
为了扩展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);
}
答案 3 :(得分:6)
在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");
}
答案 4 :(得分:2)
我在EF6(代码第一个实体重命名)中尝试了相同的操作。我只是重命名了类并使用包管理器控制台添加了迁移,并且自动为我生成了使用RenameTable(...)的迁移。我必须承认,我确保对实体的唯一更改是重命名它所以没有新列或重命名列,所以我不能确定这是EF6的东西还是只是EF(总是)能够检测到这种简单的迁移。
答案 5 :(得分:2)
在ef core中,您可以更改添加迁移后创建的迁移。然后做更新数据库。示例如下:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(name: "Type", table: "Users", newName: "Discriminator", schema: "dbo");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(name: "Discriminator", table: "Users", newName: "Type", schema: "dbo");
}
答案 6 :(得分:1)
对于EF Core migrationBuilder.RenameColumn
,通常效果很好,但有时您也必须处理索引。
migrationBuilder.RenameColumn(name: "Identifier", table: "Questions", newName: "ChangedIdentifier", schema: "dbo");
更新数据库时的错误消息示例:
Microsoft.Data.SqlClient.SqlException(0x80131904):索引 “ IX_Questions_Identifier”取决于列“ Identifier”。
索引“ IX_Questions_Identifier”取决于列“ Identifier”。
RENAME COLUMN标识符失败,因为一个或多个对象访问 此列。
在这种情况下,您必须像这样进行重命名:
migrationBuilder.DropIndex(
name: "IX_Questions_Identifier",
table: "Questions");
migrationBuilder.RenameColumn(name: "Identifier", table: "Questions", newName: "ChangedIdentifier", schema: "dbo");
migrationBuilder.CreateIndex(
name: "IX_Questions_ChangedIdentifier",
table: "Questions",
column: "ChangedIdentifier",
unique: true,
filter: "[ChangedIdentifier] IS NOT NULL");
答案 7 :(得分:0)
可以将表名和列名指定为undefined
映射的一部分。然后在迁移中没有必要这样做。
DbContext