Entity Framework CoreでPK定義の変更をする方法
2023-01-04
こんにちは、あおいです。
さて、前回の記事ではマイグレーション時に自動生成される移行コードをカスタマイズする方法について紹介させていただきました。
Entity Framework Coreで移行コードをカスタマイズする方法 | cloud config Tech Blog
PK(主キー)の定義を変更する場合も、移行コードをスクラッチでカスタマイズする必要があります。
例として桁数(10⇒15)を変更すると、EF Coreによって次の移行が生成されます。
C#protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "People",
type: "nvarchar(15)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(10)");
}
一見、これで良さそうに見えますが、ダメです。マイグレーション時に依存関係でエラーを吐きます。
オブジェクト「PK_○○」は列「○○」に依存しています。1 つ以上のオブジェクトがこの列にアクセスしているため、ALTER TABLE ALTER COLUMN は失敗しました。
そこで、今回はEntity Framework CoreでPK定義の変更をする方法について紹介したいと思います。
PK依存の場合
解決策として、以下の手順で移行コードをスクラッチでカスタマイズします。
- 主キー制約を削除 ← DropPrimaryKeyを追加で記述
- AlterColumn ← そのままでOK
- 主キー制約を作成 ← AddPrimaryKeyを追加で記述
C#
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace EFCoreSample.Migrations
{
public partial class second : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
// スクラッチで記述 ↓
migrationBuilder.DropPrimaryKey(
name: "PK_People",
table: "People");
// スクラッチで記述↑
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "People",
type: "nvarchar(15)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(10)");
// スクラッチで記述 ↓
migrationBuilder.AddPrimaryKey(
name: "PK_People",
table: "People",
column: "Name");
// スクラッチで記述 ↑
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// スクラッチで記述 ↓
migrationBuilder.DropPrimaryKey(
name: "PK_People",
table: "People");
// スクラッチで記述↑
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "People",
type: "nvarchar(10)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(15)");
// スクラッチで記述 ↓
migrationBuilder.AddPrimaryKey(
name: "PK_People",
table: "People",
column: "Name");
// スクラッチで記述 ↑
}
}
}
MigrationBuilderクラスのメソッド一覧 | Microsoft Docs
PK・FK依存の場合
PKだけでなく、FK依存もある場合、以下の手順で移行コードをスクラッチでカスタマイズします。
- 外部キー制約を削除 ← DropForeignKeyを追加で記述
- 主キー制約を削除 ← DropPrimaryKeyを追加で記述
- AlterColumn ← そのままでOK
- 主キー制約を作成 ← AddPrimaryKeyを追加で記述
- 外部キー制約を作成 ← AddForeignKeyを追加で記述
C#using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace EFCoreSample.Migrations
{
public partial class second : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
// スクラッチで記述 ここから ↓
migrationBuilder.DropForeignKey(
name: "company_fkey",
table: "Employees");
migrationBuilder.DropPrimaryKey(
name: "PK_Companys",
table: "Companys");
// スクラッチで記述 ここまで ↑
migrationBuilder.AlterColumn<string>(
name: "CompanyId",
table: "Employees",
type: "char(10)",
nullable: false,
oldClrType: typeof(string),
oldType: "char(8)");
migrationBuilder.AlterColumn<string>(
name: "CompanyId",
table: "Companys",
type: "char(10)",
nullable: false,
oldClrType: typeof(string),
oldType: "char(8)");
// スクラッチで記述 ここから ↓
migrationBuilder.AddPrimaryKey(
name: "PK_Companys",
table: "Companys",
column: "CompanyId");
migrationBuilder.AddForeignKey(
name: "company_fkey",
table: "Employees",
column: "CompanyId",
principalTable: "Companys",
principalColumn: "CompanyId",
onDelete: ReferentialAction.Cascade);
// スクラッチで記述 ここまで ↑
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// スクラッチで記述 ここから ↓
migrationBuilder.DropForeignKey(
name: "company_fkey",
table: "Employees");
migrationBuilder.DropPrimaryKey(
name: "PK_Companys",
table: "Companys");
// スクラッチで記述 ここまで ↑
migrationBuilder.AlterColumn<string>(
name: "CompanyId",
table: "Employees",
type: "char(8)",
nullable: false,
oldClrType: typeof(string),
oldType: "char(10)");
migrationBuilder.AlterColumn<string>(
name: "CompanyId",
table: "Companys",
type: "char(8)",
nullable: false,
oldClrType: typeof(string),
oldType: "char(10)");
// スクラッチで記述 ここから ↓
migrationBuilder.AddPrimaryKey(
name: "PK_Companys",
table: "Companys",
column: "CompanyId");
migrationBuilder.AddForeignKey(
name: "company_fkey",
table: "Employees",
column: "CompanyId",
principalTable: "Companys",
principalColumn: "CompanyId",
onDelete: ReferentialAction.Cascade);
// スクラッチで記述 ここまで ↑
}
}
}
MigrationBuilderクラスのメソッド一覧 | Microsoft Docs
今回はEntity Framework CoreでPK定義を変更する方法について紹介させていただきました。
コード全体を見ると、慣れない記述形式で最初は身構えてしまうかもしれませんが、手順は通常のSQLクエリと同じです。
本記事が少しでも読者の皆様のお役に立てれば幸いです。