마이그레이션 관리

모델이 변경되면 마이그레이션이 일반 개발의 일부로 추가 및 제거되고 마이그레이션 파일이 프로젝트의 소스 제어에 체크 인됩니다. 마이그레이션을 관리하려면 먼저 EF Core 명령줄 도구를 설치해야 합니다.

DbContext가 시작 프로젝트와 다른 어셈블리에 있는 경우 패키지 관리자 콘솔 도구 또는 .NET Core CLI 도구에서 대상 및 시작 프로젝트를 명시적으로 지정할 수 있습니다.

마이그레이션 추가

모델이 변경된 후 해당 변경에 대한 마이그레이션을 추가할 수 있습니다.

dotnet ef migrations add AddBlogCreatedTimestamp

마이그레이션 이름은 버전 제어 시스템의 커밋 메시지처럼 사용할 수 있습니다. 예를 들어 변경 내용이 Blog 엔터티의 새 CreatedTimestamp 속성인 경우 AddBlogCreatedTimestamp와 같은 이름을 선택할 수 있습니다.

프로젝트의 Migrations 디렉터리 아래 3개 파일이 추가됩니다.

  • XXXXXXXXXXXXXX_AddCreatedTimestamp.cs -- 주 마이그레이션 파일입니다. 마이그레이션을 적용하고(Up) 변환하는 데(Down) 필요한 작업을 포함합니다.
  • XXXXXXXXXXXXXX_AddCreatedTimestamp.Designer.cs--마이그레이션 메타데이터 파일입니다. EF에서 사용하는 정보가 들어 있습니다.
  • MyContextModelSnapshot.cs - 현재 모델의 스냅숏. 다음 마이그레이션을 추가할 때 변경 항목을 판단하는 데 사용됩니다.

파일 이름의 타임스탬프는 시간순으로 정렬되기 때문에 변경의 진행 상황을 파악할 수 있습니다.

네임스페이스

마이그레이션 파일을 자유롭게 이동하고 네임스페이스를 수동으로 변경할 수 있습니다. 새 마이그레이션은 지난 번 마이그레이션의 형제 항목으로 만들어집니다. 또는 다음과 같이 생성 시 디렉터리를 지정할 수 있습니다.

dotnet ef migrations add InitialCreate --output-dir Your/Directory

참고 항목

--namespace를 사용하여 디렉터리와 독립적으로 네임스페이스를 변경할 수도 있습니다.

마이그레이션 코드 사용자 지정

EF Core는 일반적으로 정확한 마이그레이션을 만들지만 항상 코드를 검토하고 원하는 변경 내용에 해당하는지 확인해야 합니다. 경우에 따라 이 작업을 수행해야 합니다.

열 이름 바꾸기

마이그레이션을 사용자 지정해야 하는 한 가지 주목할 만한 예는 속성 이름을 바꾸는 경우입니다. 예를 들어 속성 이름을 Name에서 FullName으로 변경하는 경우 EF Core는 다음 마이그레이션을 생성합니다.

migrationBuilder.DropColumn(
    name: "Name",
    table: "Customers");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customers",
    nullable: true);

EF Core는 일반적으로 열을 삭제하고 새 열(두 개의 별도 변경 내용)을 만드는 시기와 열 이름을 바꿔야 하는 시기를 알 수 없습니다. 위의 마이그레이션이 있는 그대로 적용되면 모든 고객 이름이 손실됩니다. 열의 이름을 바꾸려면 위에서 생성된 마이그레이션을 다음으로 바꿉니다.

migrationBuilder.RenameColumn(
    name: "Name",
    table: "Customers",
    newName: "FullName");

작업으로 인해 데이터가 손실될 수 있는 경우(예: 열 삭제) 마이그레이션 스캐폴딩 프로세스가 경고를 표시합니다. 해당 경고가 표시되면 특히 마이그레이션 코드가 정확한지 검토해야 합니다.

원시 SQL 추가

기본 제공 API를 통해 열 이름을 변경할 수 있지만 대부분의 경우 불가능합니다. 예를 들어 기존 FirstNameLastName 속성을 새 단일 FullName 속성으로 바꿀 수 있습니다. EF Core에서 생성된 마이그레이션은 다음과 같습니다.

migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer");

migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

이전과 마찬가지로 원치 않는 데이터 손실이 발생할 수 있습니다. 이전 열에서 데이터를 전송하기 위해 마이그레이션을 다시 정렬하고 다음과 같이 원시 SQL 작업을 도입합니다.

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");

원시 SQL을 통한 임의 변경

원시 SQL을 사용하여 EF Core에서 인식하지 못하는 데이터베이스 개체를 관리할 수도 있습니다. 이렇게 하려면 모델을 변경하지 않고 마이그레이션을 추가합니다. 빈 마이그레이션이 생성되고 원시 SQL 작업으로 채울 수 있습니다.

예를 들어 다음 마이그레이션은 SQL Server 저장 프로시저를 만듭니다.

migrationBuilder.Sql(
@"
    EXEC ('CREATE PROCEDURE getFullName
        @LastName nvarchar(50),
        @FirstName nvarchar(50)
    AS
        RETURN @LastName + @FirstName;')");

EXEC는 문이 SQL 일괄 처리의 첫 번째 또는 유일한 문이어야 할 때 사용됩니다. 참조된 열이 현재 테이블에 없을 때 발생할 수 있는 idempotent 마이그레이션 스크립트의 파서 오류를 해결하는 데 사용할 수도 있습니다.

다음을 포함하여 데이터베이스의 모든 측면을 관리하는 데 사용할 수 있습니다.

  • 저장 프로시저
  • 전체 텍스트 검색
  • 함수
  • 트리거

대부분의 경우 EF Core는 마이그레이션을 적용할 때 자체 트랜잭션에서 각 마이그레이션을 자동으로 래핑합니다. 아쉽게도 일부 마이그레이션 작업은 일부 데이터베이스의 트랜잭션 내에서 수행할 수 없습니다. 이러한 경우 suppressTransaction: truemigrationBuilder.Sql에 전달하여 트랜잭션에서 옵트아웃할 수 있습니다.

마이그레이션 제거

때때로 마이그레이션을 추가하고 적용하기 전에 EF Core 모델에 추가적인 변경이 필요한 경우가 있습니다. 마지막 마이그레이션을 제거하려면다음 명령을 사용합니다.

dotnet ef migrations remove

마이그레이션을 제거한 후 추가적인 모델 변경을 수행하고 다시 추가합니다.

Warning

프로덕션 데이터베이스에 이미 적용된 마이그레이션을 제거하지 마세요. 이렇게 하면 이러한 마이그레이션을 데이터베이스에서 되돌릴 수 없으며 후속 마이그레이션으로 인한 가정이 중단될 수 있습니다.

마이그레이션 나열

다음과 같이 모든 기존 마이그레이션을 나열할 수 있습니다.

dotnet ef migrations list

보류 중인 모델 변경 내용 확인

참고 항목

이 기능은 EF Core 8.0에서 추가되었습니다.

경우에 따라 마지막 마이그레이션 이후 모델 변경 내용이 있는지 확인할 수 있습니다. 이를 통해 사용자 또는 팀원이 마이그레이션을 추가하는 것을 잊은 경우를 알 수 있습니다. 이 작업을 수행하는 한 가지 방법은 이 명령을 사용하는 것입니다.

dotnet ef migrations has-pending-model-changes

context.Database.HasPendingModelChanges()를 사용하여 프로그래밍 방식으로 확인할 수도 있습니다. 마이그레이션을 추가하는 것을 잊어버린 경우 실패하는 단위 테스트를 작성하는 데 사용할 수 있습니다.

모든 마이그레이션 다시 설정

일부 극단적인 경우 모든 마이그레이션을 제거하고 다시 시작해야 할 수 있습니다. 이 작업은 마이그레이션 폴더를 삭제하고 데이터베이스를 삭제하여 쉽게 수행할 수 있습니다. 이 시점에서 전체 현재 스키마를 포함하는 새 초기 마이그레이션을 만들 수 있습니다.

또한 데이터를 잃지 않고 모든 마이그레이션을 재설정하고 단일 마이그레이션을 만들 수도 있습니다. 이를 "squashing"이라고도 하며 몇 가지 수동 작업이 포함됩니다.

  1. 문제가 발생하는 경우 데이터베이스를 백업합니다.
  2. 데이터베이스의 마이그레이션 기록 테이블에서 모든 행을 삭제합니다.(예: SQL Server의 DELETE FROM [__EFMigrationsHistory])
  3. 마이그레이션 폴더를 삭제합니다.
  4. 새 마이그레이션을 만들고 dotnet ef migrations script를 위한 SQL 스크립트를 생성합니다.
  5. 테이블이 이미 있으므로 마이그레이션 기록에 단일 행을 삽입하여 첫 번째 마이그레이션이 이미 적용되었음을 기록합니다. SQL 삽입은 위에서 생성된 SQL 스크립트의 마지막 작업이며 다음과 유사합니다(값을 업데이트하는 것을 잊지 마세요).
INSERT INTO [__EFMigrationsHistory] ([MIGRATIONID], [PRODUCTVERSION])
VALUES (N'<full_migration_timestamp_and_name>', N'<EF_version>');

Warning

마이그레이션 폴더가 삭제되면 사용자 지정 마이그레이션 코드가 손실됩니다. 유지하려면 모든 사용자 지정을 새 초기 마이그레이션에 수동으로 적용해야 합니다.

추가 리소스