Customize migration code
EF Core가 일반적으로 정확한 migrations을 생성하지만, 원하는 변경과 일치하는지 항상 code를 살펴보아야 한다. 몇몇 상황에서는 꼭 필요하다.
Column renames
한 가지 예로, property 이름변경 시, customizing migrations이 필요하다. property명을 Name에서 FullName으로 변경 시, EF Core는 다음의 migration을 생성한다.
migrationBuilder.DropColumn(
name: "Name",
table: "Customers");
migrationBuilder.AddColumn<string>(
name: "FullName",
table: "Customers",
nullable: true);
EF Core는 언제 column을 drop하고 새로 create해야 하는지 언제 column명을 변경해야 하는지 알지 못한다. 만약 위의 migration이 apply되었다면 모든 고객이름을 잃어버릴 수 있다. 컬럼명 변경을 위해서, 위의 생성된 migration을 아래와 같이 변경한다.
migrationBuilder.RenameColumn(
name: "Name",
table: "Customers",
newName: "FullName");
migration scaffolding process는 operation이 데이터 손실을 일으킬 수 있다고 경고한다. 이러한 경고를 보면, migrations code를 꼭 점검해야 한다.
Adding raw SQL
컬럼명 변경이 내장API를 통해 처리할 수 있는 반면, 많은 경우는 그렇지 않다. 예를들어, 기존 FirstName, LastName properties를 하나의 새로운 FullName property로 대체하고 싶은 경우이다. EF Core에 의해 생성된 migration은 아래와 같다.
migrationBuilder.DropColumn(
name: "FirstName",
table: "Customer");
migrationBuilder.DropColumn(
name: "LastName",
table: "Customer");
migrationBuilder.AddColumn<string>(
name: "FullName",
table: "Customer",
nullable: true);
이전처럼, 원치않는 데이터 손실이 발생한다. old columns의 data를 이전하기 위해, raw SQL 을 추가함으로 migration을 재정비한다.
migrationBuilder.AddColumn<string>(
name: "FullName",
table: "Customer",
nullable: true);
migrationBuilder.Sql(
@"
UPDATE Customer
SET FullName = FirstName + ' ' + LastName;
");
migrationBuilder.DropColumn(
name: "FirstName",
table: "Customer");
migrationBuilder.DropColumn(
name: "LastName",
table: "Customer");
Arbitrary changes via raw SQL
Raw SQL은 또한 EF Core가 인식하지 않는 database objects를 관리하는데 사용할 수도 있따. 이를 위해, model변경 없이 add migration을 한다. 그러면 빈 migration이 생성되고, raw SQL을 입력할 수 있다.
아래 migration은 SQL Server stored procedure를 생성한다.
migrationBuilder.Sql(
@"
EXEC ('CREATE PROCEDURE getFullName
@LastName nvarchar(50),
@FirstName nvarchar(50)
AS
RETURN @LastName + @FirstName;')");
EXEC는 SQL batch에서 반드시 처음에 오거나, only one인 statement에 사용되어야 한다.
해당 방법으로, 아래 항목들을 관리할 수 있다.
- Stored procedures
- Full-Text Search
- Functions
- Triggers
- Views
대부분의 경우, EF Core는 migration을 apply할 때, 자동으로 transaction으로 감싼다. 안타깝게도, 어떤 migrations은 몇몇 database에서 transaction 내부에서 실행되지 못한다. 이런 경우, migrationBuilder.Sql에 suppressTransaction:true값을 전달하므로 transaction 밖에서 실행하도록 선택할 수 있다.
Resetting all migrations
In some extreme cases, it may be necessary to remove all migrations and start over. This can be easily done by deleting your Migrations folder and dropping your database; at that point you can create a new initial migration, which will contain your entire current schema.
It's also possible to reset all migrations and create a single one without losing your data. This is sometimes called "squashing", and involves some manual work:
극한의 상황으로, 모든 migrations을 지우고 다시 시작해야 할 수 있다. Migration 폴더를 통째로 지우고, database를 drop하므로 쉽게 처리할 수 있다. 이때, 전체 current schema를 포함하는 새로운 initial migration을 생성할 수 있다.
데이터 손실 없이 모든 migrations을 reset하고 하나로 만드는 것도 가능하다. 이것을 때때로 squashing이라고 하며, manual work가 있다.
- 만일을 위해, database를 백업해 둔다.
- database에 있는 migration history table의 모든 row를 delete한다.
- 프로젝트의 Migrations 폴더를 삭제한다.
- 새로운 migration을 생성하고, SQL script도 생성한다.
- migration history table에 이미 적용된 first migration을 기록하기 위해, 하나의 row를 insert한다. insert SQL은 위에 생성한 SQL script에 마지막 operation이며, 다음과 유사하다.
INSERT INTO [__EFMigrationsHistory] ([MIGRATIONID], [PRODUCTVERSION])
VALUES (N'<full_migration_timestamp_and_name>', N'<EF_version>');
어떠한 custom migration code라도 Migrations 폴더가 삭제되면 사라진다. 어떤 customizations이든, 보존되기 위해 수동으로 initial migration에 추가되어야 한다.
'Entity Framework Core' 카테고리의 다른 글
Entity Framework Core] 팀 개발 환경에서 Migrations (0) | 2023.07.20 |
---|---|
Entity Framework Core] Migrations 반영 (0) | 2023.07.20 |
Entity Framework Core] transactions (0) | 2023.07.14 |
Entity Framework Core] Loading pattern (0) | 2023.07.14 |
Entity Framework Core] .AsNoTracking()이란? (0) | 2023.06.09 |
댓글