いくつかのエンティティとそのナビゲーションプロパティの名前を変更し、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
コードを自動的に作成する2ステップのアプローチに従うことができます。
ステップ1ColumnAttribute
を使用して新しい列名を導入し、次に移行を追加します(例:Add-Migration ColumnChanged
)
public class ReportPages
{
[Column("Section_Id")] //Section_Id
public int Group_Id{get;set}
}
Step-Twoプロパティ名を変更し、パッケージマネージャーコンソールで同じ移行(例: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");
});
}
}