C# 实体框架迁移重命名表和列
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13296996/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Entity Framework Migrations renaming tables and columns
提问by Chev
I renamed a a couple entities and their navigation properties and generated a new Migration in EF 5. As is usual with renames in EF migrations, by default it was going to drop objects and recreate them. That isn't what I wanted so I pretty much had to build the migration file from scratch.
我重命名了一对实体及其导航属性,并在 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");
}
All I'm trying to do is rename dbo.ReportSectionsto dbo.ReportPagesand then dbo.ReportSectionGroupsto dbo.ReportSections. Then I need to rename the foreign key column on dbo.ReportPagesfrom Group_Idto Section_Id.
我要做的就是重命名dbo.ReportSections为dbo.ReportPages,然后重命名dbo.ReportSectionGroups为dbo.ReportSections. 然后,我需要外键列上的重命名dbo.ReportPages,从Group_Id到Section_Id。
I am dropping the foreign keys and indexes linking the tables together, then I am renaming the tables and the foreign key column, then I'm adding the indexes and foreign keys again. I assumed this was going to work but I am getting a SQL error.
我删除将表链接在一起的外键和索引,然后重命名表和外键列,然后再次添加索引和外键。我以为这会起作用,但我收到了 SQL 错误。
Msg 15248, Level 11, State 1, Procedure sp_rename, Line 215 Either the parameter @objname is ambiguous or the claimed @objtype (COLUMN) is wrong. Msg 4902, Level 16, State 1, Line 10 Cannot find the object "dbo.ReportSections" because it does not exist or you do not have permissions.
消息 15248,级别 11,状态 1,过程 sp_rename,第 215 行参数@objname 不明确或声明的@objtype (COLUMN) 是错误的。消息 4902,级别 16,状态 1,第 10 行 找不到对象“dbo.ReportSections”,因为它不存在或您没有权限。
I'm not having an easy time figuring out what is wrong here. Any insight would be tremendously helpful.
我不是很容易弄清楚这里出了什么问题。任何见解都会非常有帮助。
采纳答案by Chev
Nevermind. I was making this way more complicated than it really needed to be.
没关系。我让这种方式变得比实际需要的更复杂。
This was all that I needed. The rename methods just generate a call to the sp_renamesystem stored procedure and I guess that took care of everything, including the foreign keys with the new column name.
这就是我所需要的。重命名方法只是生成对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");
}
回答by naskew
I just tried the same in EF6 (code first entity rename). I simply renamed the class and added a migration using the package manager console and voila, a migration using RenameTable(...) was automatically generated for me. I have to admit that I made sure the only change to the entity was renaming it so no new columns or renamed columns so I cannot be certain if this is an EF6 thing or just that EF was (always) able to detect such simple migrations.
我刚刚在 EF6 中尝试了相同的方法(代码第一个实体重命名)。我只是重命名了类并使用包管理器控制台添加了一个迁移,瞧,使用 RenameTable(...) 的迁移是自动为我生成的。我必须承认,我确保对实体的唯一更改是重命名它,因此没有新列或重命名列,因此我无法确定这是 EF6 的事情还是只是 EF(总是)能够检测到这种简单的迁移。
回答by Hossein Narimani Rad
If you don't like writing/changing the required code in the Migration class manually, you can follow a two-step approach which automatically make the RenameColumncode which is required:
如果您不喜欢手动编写/更改 Migration 类中所需的代码,您可以按照两步方法自动RenameColumn生成所需的代码:
Step OneUse the ColumnAttributeto introduce the new column name and then add-migration (e.g. Add-Migration ColumnChanged)
第一步使用ColumnAttribute来引入新的列名,然后添加迁移(例如Add-Migration ColumnChanged)
public class ReportPages
{
[Column("Section_Id")] //Section_Id
public int Group_Id{get;set}
}
Step-Twochange the property name and again apply to same migration (e.g. Add-Migration ColumnChanged -force) in the Package Manager Console
第二步更改属性名称并再次应用于Add-Migration ColumnChanged -force包管理器控制台中的相同迁移(例如)
public class ReportPages
{
[Column("Section_Id")] //Section_Id
public int Section_Id{get;set}
}
If you look at the Migration class you can see the automatically code generated is RenameColumn.
如果您查看 Migration 类,您可以看到自动生成的代码是RenameColumn.
回答by Etienne Morin
To expand a bit on Hossein Narimani Rad's answer, you can rename both a table and columns using System.ComponentModel.DataAnnotations.Schema.TableAttribute and System.ComponentModel.DataAnnotations.Schema.ColumnAttribute respectively.
要扩展 Hossein Narimani Rad 的回答,您可以分别使用 System.ComponentModel.DataAnnotations.Schema.TableAttribute 和 System.ComponentModel.DataAnnotations.Schema.ColumnAttribute 重命名表和列。
This has a couple benefits:
这有几个好处:
- Not only will this create the the name migrations automatically, but
- it will also deliciously delete any foreign keys and recreate them against the new table and column names, giving the foreign keys and constaints proper names.
- All this without losing any table data
- 这不仅会自动创建名称迁移,而且
- 它还将删除任何外键并根据新表和列名称重新创建它们,并给出外键和常量名称。
- 所有这一切都不会丢失任何表数据
For example, adding [Table("Staffs")]:
例如,添加[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; }
}
Will generate the migration:
将生成迁移:
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);
}
回答by Martin Staufcik
Table names and column names can be specified as part of the mapping of DbContext. Then there is no need to do it in migrations.
表名和列名可以指定为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");
});
}
}
回答by mirind4
In EF Core, I use the following statements to rename tables and columns:
在 EF Core 中,我使用以下语句重命名表和列:
As for renaming tables:
至于重命名表:
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");
}
As for renaming columns:
至于重命名列:
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");
}
回答by Abdus Salam Azad
In ef core, you can change the migration that was created after add migration. And then do update-database. A sample has given below:
在 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");
}

