마이그레이션 적용

마이그레이션이 추가되면 배포하고 데이터베이스에 적용해야 합니다. 이 작업을 수행하기 위한 다양한 전략이 있으며 일부는 프로덕션 환경에 더 적합하고 다른 일부는 개발 수명 주기에 적합합니다.

참고 항목

배포 전략이 무엇이든 프로덕션 데이터베이스에 적용하기 전에 항상 생성된 마이그레이션을 검사하고 테스트합니다. 마이그레이션은 의도 이름을 바꿀 때 열을 삭제하거나 데이터베이스에 적용할 때 다양한 이유로 실패할 수 있습니다.

SQL 스크립트

프로덕션 데이터베이스에 마이그레이션을 배포하는 권장 방법은 SQL 스크립트를 생성하는 것입니다. 이 전략의 장점은 다음과 같습니다.

  • 정확성을 위해 SQL 스크립트를 검토할 수 있습니다. 이는 프로덕션 데이터베이스에 스키마 변경 내용을 적용하는 것이 데이터 손실을 수반할 수 있는 잠재적으로 위험한 작업이므로 중요합니다.
  • 경우에 따라 프로덕션 데이터베이스의 특정 요구 사항에 맞게 스크립트를 조정할 수 있습니다.
  • SQL 스크립트는 배포 기술과 함께 사용할 수 있으며 CI 프로세스의 일부로 생성될 수도 있습니다.
  • SQL 스크립트는 DBA에 제공할 수 있으며 별도로 관리 및 보관할 수 있습니다.

기본 사용법

다음은 빈 데이터베이스에서 최신 마이그레이션으로 SQL 스크립트를 생성합니다.

dotnet ef migrations script

From을 사용할 경우(implied에 대해)

다음은 지정된 마이그레이션에서 최신 마이그레이션으로의 SQL 스크립트를 생성합니다.

dotnet ef migrations script AddNewTables

From 및 To를 사용할 경우

다음은 지정된 from 마이그레이션에서 지정된 to 마이그레이션으로의 SQL 스크립트를 생성합니다.

dotnet ef migrations script AddNewTables AddAuditTable

롤백 스크립트를 생성하기 위해 to보다 최신인 from을 사용할 수 있습니다.

Warning

‘잠재적 데이터 손실 시나리오를 기록해 두세요.’

스크립트 생성은 다음 두 인수를 수락하여 생성해야 하는 마이그레이션 범위를 나타냅니다.

  • from 마이그레이션은 스크립트를 실행하기 전에 데이터베이스에 적용된 마지막 마이그레이션이 되어야 합니다. 적용된 마이그레이션이 없으면 0(기본값)을 지정합니다.
  • to 마이그레이션을 스크립트를 실행한 후에 데이터베이스에 적용된 마지막 마이그레이션이 되어야 합니다. 기본값은 프로젝트의 마지막 마이그레이션입니다.

Idempotent SQL 스크립트

위에서 생성된 SQL 스크립트는 한 마이그레이션에서 다른 마이그레이션으로 스키마를 변경하기 위해만 적용할 수 있습니다. 스크립트를 적절하게 적용하고 올바른 마이그레이션 상태의 데이터베이스에만 적용해야 합니다. EF Core는 또한 마이그레이션 기록 테이블을 통해 이미 적용된 마이그레이션을 내부적으로 확인하고 누락된 마이그레이션만 적용하는 멱등원 스크립트 생성을 지원합니다. 데이터베이스에 적용된 마지막 마이그레이션을 잘 모르거나 각기 다른 마이그레이션 상태일 수 있는 여러 데이터베이스에 배포할 때 이것이 유용합니다.

다음은 멱등 마이그레이션을 생성합니다.

dotnet ef migrations script --idempotent

명령줄 도구

EF 명령줄 도구를 사용하여 데이터베이스에 마이그레이션을 적용할 수 있습니다. 마이그레이션의 로컬 개발 및 테스트에 생산성이 있지만 프로덕션 데이터베이스를 관리하는 데는 이 방법이 적합하지 않습니다.

  • SQL 명령은 개발자에게 검사하거나 수정할 기회를 주지 않고 도구에서 직접 적용됩니다. 이는 프로덕션 환경에서 위험할 수 있습니다.
  • .NET SDK 및 EF 도구는 프로덕션 서버에 설치해야 하며 프로젝트의 소스 코드가 필요합니다.

참고 항목

기본적으로 각 마이그레이션은 자체 트랜잭션에 적용됩니다. 이 영역의 향후 개선 사항에 대한 자세한 내용은 GitHub 이슈 #22616을 참조하세요.

다음은 데이터베이스를 최신 마이그레이션으로 업데이트합니다.

dotnet ef database update

다음은 지정된 마이그레이션으로 데이터베이스를 업데이트합니다.

dotnet ef database update AddNewTables

이전 마이그레이션으로 롤백하는 데도 사용할 수 있습니다.

Warning

‘잠재적 데이터 손실 시나리오를 기록해 두세요.’

명령줄 도구를 통해 마이그레이션을 적용하는 방법에 대한 자세한 내용은 EF Core 도구 참조를 참조하세요.

번들

마이그레이션 번들은 데이터베이스에 마이그레이션을 적용하는 데 사용할 수 있는 단일 파일 실행 파일입니다. SQL 스크립트 및 명령줄 도구의 몇 가지 단점을 해결합니다.

  • SQL 스크립트를 실행하려면 추가 도구가 필요합니다.
  • 이러한 도구의 트랜잭션 처리 및 계속 오류 발생 동작은 일관되지 않으며 경우에 따라 예기치 않은 경우가 있습니다. 마이그레이션을 적용할 때 오류가 발생하면 데이터베이스가 정의되지 않은 상태로 남을 수 있습니다.
  • 번들은 CI 프로세스의 일부로 생성될 수 있으며 나중에 배포 프로세스의 일부로 쉽게 실행할 수 있습니다.
  • 번들은 .NET SDK 또는 EF 도구(또는 자체 포함 시 .NET 런타임)를 설치하지 않고도 실행할 수 있으며 프로젝트의 소스 코드가 필요하지 않습니다.

다음은 번들을 생성합니다.

dotnet ef migrations bundle

다음은 Linux용 자체 포함 번들을 생성합니다.

dotnet ef migrations bundle --self-contained -r linux-x64

번들을 만드는 방법에 대한 자세한 내용은 EF Core 도구 참조를 참조하세요.

efbundle

결과 실행 파일의 이름은 기본적으로 efbundle로 지정됩니다. 데이터베이스를 최신 마이그레이션으로 업데이트하는 데 사용할 수 있습니다. dotnet ef database update 또는 Update-Database를 실행하는 것과 같습니다.

인수:

인수 설명
<MIGRATION> 대상 마이그레이션입니다. '0'이면 모든 마이그레이션이 되돌아갑니다. 기본값은 마지막 마이그레이션입니다.

옵션:

옵션 Short 설명
--connection <CONNECTION> 데이터베이스에 대한 연결 문자열입니다. 기본값은 AddDbContext 또는 OnConfiguring에 지정된 입니다.
--verbose -v 자세한 정보 출력을 표시합니다.
--no-color 출력에 색을 지정하지 마세요.
--prefix-output 수준이 있는 접두사 출력입니다.

다음 예제에서는 지정된 사용자 이름 및 암호를 사용하여 로컬 SQL Server 인스턴스에 마이그레이션을 적용합니다.

.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password=myPassword'

Warning

번들과 함께 appsettings.json을 복사하는 것을 잊지 마세요. 번들은 실행 디렉터리에 appsettings.json이 있어야 합니다.

마이그레이션 번들 예제

번들에는 포함할 마이그레이션이 필요합니다. 첫 번째 마이그레이션 만들기에 설명된 대로 dotnet ef migrations add를 사용하여 만들어집니다. 마이그레이션을 배포할 준비가 되면 dotnet ef migrations bundle을 사용하여 번들을 만듭니다. 예시:

PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>

출력은 대상 운영 체제에 적합한 실행 파일입니다. 내 경우에는 Windows x64이므로 로컬 폴더에 efbundle.exe가 삭제됩니다. 이 실행 파일을 실행하면 그 안에 포함된 마이그레이션이 적용됩니다.

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903083845_MyMigration'.
Done.
PS C:\local\AllTogetherNow\SixOh>

dotnet ef database update 또는 Update-Database와 마찬가지로 마이그레이션은 아직 적용되지 않은 경우에만 데이터베이스에 적용됩니다. 예를 들어, 동일한 번들을 다시 실행해도 적용되는 새 마이그레이션이 없으므로 아무 작업도 수행하지 않습니다.

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
No migrations were applied. The database is already up to date.
Done.
PS C:\local\AllTogetherNow\SixOh>

그러나 모델이 변경되고 dotnet ef migrations add를 사용하여 더 많은 마이그레이션이 생성된 경우에는 적용할 준비가 된 새 실행 파일에 번들로 묶을 수 있습니다. 예시:

PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add SecondMigration
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations add Number3
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\local\AllTogetherNow\SixOh> dotnet ef migrations bundle --force
Build started...
Build succeeded.
Building bundle...
Done. Migrations Bundle: C:\local\AllTogetherNow\SixOh\efbundle.exe
PS C:\local\AllTogetherNow\SixOh>

--force 옵션을 사용하여 기존 번들을 새 번들로 덮어쓸 수 있습니다.

이 새 번들을 실행하면 데이터베이스에 새로운 두 개의 마이그레이션이 적용됩니다.

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>

기본적으로 번들은 애플리케이션 구성의 데이터베이스 연결 문자열을 사용합니다. 그러나 명령줄에서 연결 문자열을 전달하여 다른 데이터베이스를 마이그레이션할 수 있습니다. 예시:

PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe --connection "Data Source=(LocalDb)\MSSQLLocalDB;Database=SixOhProduction"
Applying migration '20210903083845_MyMigration'.
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>

참고 항목

이번에는 프로덕션 데이터베이스에 아직 적용되지 않았기 때문에 세 개의 마이그레이션이 모두 적용되었습니다.


런타임에 마이그레이션 적용

애플리케이션 자체가 일반적으로 시작하는 동안 프로그래밍 방식으로 마이그레이션을 적용할 수 있습니다. 마이그레이션의 로컬 개발 및 테스트에 대한 생산성이 높지만 이 방법은 다음과 같은 이유로 프로덕션 데이터베이스를 관리하는 데 적합하지 않습니다.

  • 애플리케이션의 여러 인스턴스가 실행 중인 경우 두 애플리케이션 모두 동시에 마이그레이션을 적용하고 실패(또는 더 나쁜 경우 데이터 손상 발생)를 시도할 수 있습니다.
  • 마찬가지로 다른 애플리케이션이 데이터베이스를 마이그레이션하는 동안 애플리케이션이 데이터베이스에 액세스하는 경우 심각한 문제가 발생할 수 있습니다.
  • 데이터베이스 스키마를 수정하려면 애플리케이션에 상승된 액세스 권한이 있어야 합니다. 일반적으로 프로덕션 환경에서 애플리케이션의 데이터베이스 권한을 제한하는 것이 좋습니다.
  • 문제가 발생한 경우 적용된 마이그레이션을 롤백할 수 있어야 합니다. 다른 전략은 이를 쉽고 기본적으로 제공합니다.
  • SQL 명령은 개발자에게 검사하거나 수정할 기회를 주지 않고 프로그램에서 직접 적용됩니다. 이는 프로덕션 환경에서 위험할 수 있습니다.

프로그래밍 방식으로 마이그레이션을 적용하려면 context.Database.Migrate()를 호출합니다. 예를 들어 일반적인 ASP.NET 애플리케이션은 다음을 수행할 수 있습니다.

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    using (var scope = host.Services.CreateScope())
    {
        var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        db.Database.Migrate();
    }

    host.Run();
}

Migrate()IMigrator 서비스를 기반으로 구성되므로 더 고급 시나리오에 사용할 수 있습니다. myDbContext.GetInfrastructure().GetService<IMigrator>()를 사용하여 액세스합니다.

Warning

  • 프로덕션 환경에서 이 방법을 사용하기 전에 신중하게 고려해야 합니다. 경험에 따르면 이 배포 전략의 단순성은 만드는 문제보다 더 큽니다. 대신 마이그레이션에서 SQL 스크립트를 생성하는 것이 좋습니다.
  • Migrate()에 앞서 EnsureCreated()를 호출하지 않습니다. EnsureCreated()는 마이그레이션을 무시하고 스키마를 만들어 Migrate()에 실패합니다.