個別の移行プロジェクトの使用

移行は、 DbContextを含むプロジェクトとは異なるプロジェクトに格納できます。 これは、アプリケーション プロジェクトがプラットフォーム固有 (WinUI、.NET MAUI、Blazor WebAssembly、Azure Functionsなど) の場合、または特定のランタイム識別子 (RID) を対象とする場合に推奨されます。 また、複数の移行セットを維持するためにも使用できます。

Tip

この記事の サンプルは、GitHub で確認できます。

プロジェクトのレイアウト

このサンプルでは、次の 3 つのプロジェクトを使用します。

プロジェクト 責任 References
WebApplication1.Data DbContextとエンティティ型を所有します EF Core プロバイダー
WebApplication1.Migrations 移行、モデル スナップショット、およびデザイン時コンテキストの作成を所有します データ プロジェクト、EF Core プロバイダー、および Microsoft.EntityFrameworkCore.Design
WebApplication1 アプリケーションを実行する データ プロジェクトと移行プロジェクト

アプリケーションは、実行時に移行を検出または適用するときに、たとえば Migrateを呼び出すことによって、移行プロジェクトへの参照を必要とします。 移行がデプロイ成果物によってのみ適用され、アプリケーションがそれらを読み込まない場合、その参照は必要ありません。

プロジェクトを構成する

  1. 移行用のクラス ライブラリを作成し、 DbContextを含むプロジェクトへの参照を追加します。

  2. データベース プロバイダーと Microsoft.EntityFrameworkCore.Design を移行プロジェクトに追加します。 設計パッケージをプライベート開発依存関係としてマークします。

    <ItemGroup>
      <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="...">
        <PrivateAssets>all</PrivateAssets>
        <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      </PackageReference>
      <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="..." />
    </ItemGroup>
    
    <ItemGroup>
      <ProjectReference Include="..\WebApplication1.Data\WebApplication1.Data.csproj" />
    </ItemGroup>
    
  3. 移行プロジェクトに IDesignTimeDbContextFactory<TContext> を実装します。 ファクトリでは、アプリケーション プロジェクトを実行せずに、ツールでコンテキストを作成できます。

    public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
    {
        public ApplicationDbContext CreateDbContext(string[] args)
        {
            var connectionString = args.FirstOrDefault()
                ?? @"Server=(localdb)\mssqllocaldb;Database=WebApplication1;Trusted_Connection=True";
    
            var options = new DbContextOptionsBuilder<ApplicationDbContext>()
                .UseSqlServer(
                    connectionString,
                    sqlServer => sqlServer.MigrationsAssembly(typeof(ApplicationDbContextFactory).Assembly.GetName().Name))
                .Options;
    
            return new ApplicationDbContext(options);
        }
    }
    

    デザイン時プロバイダーとモデルの構成は、ランタイム構成と一貫性を保ちます。 このサンプルでは、省略可能な接続文字列引数を受け取り、引数が指定されていない場合はローカル開発接続を使用します。

  4. 実行時にコンテキストを登録するときに、移行アセンブリを構成します。

    services.AddDbContext<ApplicationDbContext>(
        options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection"),
                x => x.MigrationsAssembly("WebApplication1.Migrations")));
    
  5. アプリケーションが移行を適用する場合、または実行時にそれらを検出する場合は、アプリケーションから移行プロジェクトへの通常の参照を追加します。

    <ItemGroup>
      <ProjectReference Include="..\WebApplication1.Migrations\WebApplication1.Migrations.csproj" />
    </ItemGroup>
    

    データ プロジェクトは、移行プロジェクトを参照してはなりません。 移行プロジェクトが既にデータ プロジェクトを参照しているため、循環依存関係が作成されます。

  6. 移行が既に存在する場合は、すべての移行ファイルとモデル スナップショットを移行プロジェクトに移動し、名前空間を更新します。 既存の移行がない場合、デザイン時ファクトリでは、移行プロジェクトで最初の移行を直接作成できます。

ツールを使用する

移行プロジェクトを ターゲット プロジェクトとスタートアップ プロジェクトの両方として使用します。 ターゲット プロジェクトは生成されたファイルを受け取りますが、スタートアップ プロジェクトはツールによってビルドおよび実行されます。 このレイアウトでは、両方に移行プロジェクトを使用すると、ツールでアプリケーションのスタートアップ コードが実行されなくなります。

ソリューション ディレクトリから次のコマンドを実行します。

dotnet ef migrations add NewMigration \
    --project WebApplication1.Migrations \
    --startup-project WebApplication1.Migrations

同じプロジェクト オプションが他のコマンドに適用されます。

dotnet ef migrations list \
    --project WebApplication1.Migrations \
    --startup-project WebApplication1.Migrations

dotnet ef migrations script --output artifacts/migrations.sql \
    --project WebApplication1.Migrations \
    --startup-project WebApplication1.Migrations

dotnet ef migrations bundle --output artifacts/efbundle \
    --project WebApplication1.Migrations \
    --startup-project WebApplication1.Migrations

EF Core 11 以降では、繰り返しのプロジェクト オプションを .config/dotnet-ef.jsonに格納できます。

--no-buildを使用してコマンドを実行する前、または別のプロセスがその出力を使用する前に、移行プロジェクトをビルドします。 通常の dotnet ef コマンドは、ターゲット プロジェクトとスタートアップ プロジェクトを自動的にビルドします。

プラットフォーム固有のアプリケーション

EF ツールのスタートアップ プロジェクトとしてプラットフォーム固有のアプリケーション プロジェクトを使用しないでください。 モバイル、ブラウザー、デスクトップ、関数、RID 固有のプロジェクトでは、 dotnet ef 実行できないワークロードまたはネイティブ ホストが必要な場合があります。 EF Core 11 以降では、プラットフォーム固有のスタートアップ プロジェクトが使用されると、ツールによって警告が表示されます。

上記のレイアウトは、.NET MAUI、WinUI、Blazor WebAssembly、Azure Functions、および同様のアプリケーションに使用します。

  1. コンテキストとエンティティの種類を共有データ プロジェクトに配置します。
  2. 移行とIDesignTimeDbContextFactory<TContext>は、通常のクロスプラットフォーム .NET プロジェクトに配置します。
  3. 移行プロジェクトをターゲット プロジェクトとスタートアップ プロジェクトとして使用してツールを実行します。
  4. アプリケーションが実行時に移行を読み込んだり適用したりする場合にのみ、アプリケーションから移行プロジェクトを参照します。

Xamarinおよび MAUI プラットフォーム プロジェクトの直接ツールサポートは計画されていません。dotnet/efcore#7152 を参照してください。 Xamarinアプリケーションは、最初に.NET MAUIにアップグレードする必要があります。

プロセス アーキテクチャ

ツールを実行するプロセスは、すべてのデザイン時アセンブリを読み込める必要があります。 64 ビットのVisual Studioまたは.NET プロセスでは、x86 のみのスタートアップ アセンブリを読み込めません。Arm64 やその他のアーキテクチャにも同じ制約が適用されます。 AnyCPU 移行プロジェクトを優先します。 デザイン時の依存関係に特定のアーキテクチャが必要な場合は、一致する.NET SDK を明示的に呼び出します。

デザイン時プロセス アーキテクチャは、デプロイ ターゲットとは別です。 バンドルを作成するときは、 --target-runtime または -TargetRuntime を使用して、 linux-arm64osx-arm64などのデプロイ RID の成果物を生成します。