Een afzonderlijk project voor migraties gebruiken

U kunt migraties opslaan in een ander project dan het project dat uw DbContextproject bevat. Dit wordt aanbevolen wanneer het toepassingsproject platformspecifiek is, zoals WinUI, .NET MAUI, Blazor WebAssembly of Azure Functions, of wanneer het gericht is op een specifieke runtime-id (RID). Het kan ook worden gebruikt om meer dan één set migraties te onderhouden.

Projectindeling

In het voorbeeld worden drie projecten gebruikt:

Project Verantwoordelijkheid References
WebApplication1.Data Eigenaar van de DbContext en entiteitstypen EF Core-provider
WebApplication1.Migrations Eigenaar van migraties, de momentopname van het model en het maken van ontwerptijdcontext Gegevensproject, EF Core-provider en Microsoft.EntityFrameworkCore.Design
WebApplication1 De toepassing uitvoeren Gegevensproject en migratieproject

De toepassing heeft een verwijzing naar het migratieproject nodig wanneer deze migraties tijdens runtime detecteert of toepast, bijvoorbeeld door aan te roepen Migrate. Als migraties alleen worden toegepast door een implementatieartefact en de toepassing deze nooit laadt, is die verwijzing niet vereist.

De projecten configureren

  1. Maak een klassebibliotheek voor de migraties en voeg een verwijzing toe naar het project met de DbContext.

  2. Voeg de databaseprovider en Microsoft.EntityFrameworkCore.Design het migratieproject toe. Markeer het ontwerppakket als een afhankelijkheid voor privéontwikkeling:

    <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. Implementeren IDesignTimeDbContextFactory<TContext> in het migratieproject. Met de factory kunnen de hulpprogramma's de context maken zonder het toepassingsproject uit te voeren:

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

    Zorg ervoor dat de ontwerp-tijdprovider en modelconfiguratie consistent blijven met de runtimeconfiguratie. Het voorbeeld accepteert een optioneel verbindingsreeks argument en gebruikt een lokale ontwikkelverbinding wanneer er geen argument wordt opgegeven.

  4. Configureer de migratieassembly bij het registreren van de context tijdens runtime:

    services.AddDbContext<ApplicationDbContext>(
        options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection"),
                x => x.MigrationsAssembly("WebApplication1.Migrations")));
    
  5. Als de toepassing migraties toepast of op een andere manier detecteert tijdens runtime, voegt u een normale verwijzing van de toepassing toe aan het migratieproject:

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

    Het gegevensproject mag niet verwijzen naar het migratieproject. Hierdoor ontstaat een kringafhankelijkheid omdat het migratieproject al verwijst naar het gegevensproject.

  6. Als er al migraties bestaan, verplaatst u alle migratiebestanden en de momentopname van het model naar het migratieproject en werkt u hun naamruimten bij. Wanneer er geen bestaande migraties zijn, staat de ontwerptijdfactory toe dat de eerste migratie rechtstreeks in het migratieproject wordt gemaakt.

De hulpprogramma's gebruiken

Gebruik het migratieproject als zowel het doelproject als het opstartproject. Het doelproject ontvangt gegenereerde bestanden, terwijl het opstartproject wordt gebouwd en uitgevoerd door de hulpprogramma's. In deze indeling voorkomt u met behulp van het migratieproject voor beide dat de hulpprogramma's opstartcode van de toepassing uitvoeren.

Voer deze opdrachten uit vanuit de oplossingsmap:

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

Dezelfde projectopties zijn van toepassing op andere opdrachten:

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

Vanaf EF Core 11 kunnen herhaalde projectopties worden opgeslagen in .config/dotnet-ef.json.

Bouw het migratieproject voordat u opdrachten uitvoert met --no-buildof voordat een ander proces de uitvoer verbruikt. Met een normale dotnet ef opdracht worden de doel- en opstartprojecten automatisch gebouwd.

Platformspecifieke toepassingen

Gebruik geen platformspecifiek toepassingsproject als opstartproject voor EF-hulpprogramma's. Mobiele, browser-, desktop-, functie- en RID-specifieke projecten kunnen een workload of systeemeigen host vereisen die dotnet ef niet kan worden uitgevoerd. Vanaf EF Core 11 waarschuwen de hulpprogramma's wanneer een platformspecifiek opstartproject wordt gebruikt.

Gebruik de hierboven beschreven indeling voor .NET MAUI, WinUI, Blazor WebAssembly, Azure Functions en vergelijkbare toepassingen:

  1. Plaats de context- en entiteitstypen in een gedeeld gegevensproject.
  2. Zet migraties en IDesignTimeDbContextFactory<TContext> in een normaal platformoverschrijdend .NET project.
  3. Voer de hulpprogramma's uit met het migratieproject als doel- en opstartproject.
  4. Verwijs alleen naar het migratieproject van de toepassing als de toepassing tijdens runtime wordt geladen of migraties toepast.

Directe ondersteuning voor hulpprogramma's voor Xamarin- en TENANT-platformprojecten is niet gepland. Zie dotnet/efcore#7152. Xamarin toepassingen moeten eerst worden bijgewerkt naar .NET MAUI.

Procesarchitectuur

Het proces waarop de hulpprogramma's worden uitgevoerd, moet elke ontwerp-tijdassembly kunnen laden. Een 64-bits Visual Studio of .NET proces kan geen opstartassembly met x86 laden en dezelfde beperking is van toepassing op Arm64 en andere architecturen. Geef de voorkeur aan een AnyCPU-migratieproject. Als ontwerptijdafhankelijkheden een specifieke architectuur vereisen, roept u expliciet een overeenkomende .NET SDK aan.

De ontwerp-tijdprocesarchitectuur staat los van het implementatiedoel. Wanneer u een bundel maakt, gebruikt --target-runtime of -TargetRuntime genereert u een artefact voor de implementatie-RID, zoals linux-arm64 of osx-arm64.