This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Sunday, 23 November 2025
Uitvoeren MigrateAsync() bij het opstarten? U geeft uw app database eigenaar rechten en hopen dat er niets mis gaat. Er is een betere manier - EF migratie bundels kunt u migraties uitvoeren als een gecontroleerde CI stap, het houden van uw productie app veilig. Maar hier is het ding: soms is de "verkeerde" manier is eigenlijk prima. Laten we verkennen wanneer om elke aanpak te gebruiken.
Officiële documenten: Overzicht migraties | Migratie toepassen | Bundelsunit synonyms for matching user input
Deze blog gebruikt MigrateAsync() bij het opstarten - de aanpak die ik je ga vertellen om niet te gebruiken. Hier is waarom dat oké is voor mij, en waarom het waarschijnlijk niet voor jou is.
In mijn Program.cs bestand Ik heb het volgende:
using (var scope = app.Services.CreateScope())
{
var blogContext = scope.ServiceProvider.GetRequiredService<IMostlylucidDBContext>();
await blogContext.Database.MigrateAsync();
}
MigrateAsync() van toepassing in afwachting van migraties en maakt de database indien nodig. Simpel - maar problematisch:
db_owner Je gaf je runtime app de sleutels om tafels te laten vallen.Waarom ik ermee weg kom: publieke data, een enkel Docker netwerk, persoonlijk project. Dat kun je waarschijnlijk niet.
Een EF-bundel is een zelfstandig uitvoerbaar bestand dat uw gecompileerde migraties bevat. dotnet ef database update verpakt in een standalone .exe.
Waarom bundels winnen:
db_owner; alleen CI runner doet, alleen tijdens implementatieOpmerking: Voor de beveiliging van productiekwaliteit, gebruik Beheerde identiteit Maar bundels zijn nog steeds een belangrijke stap hoger dan runtime migraties.
- name: Install EF Core tools
run: dotnet tool install --global dotnet-ef
- name: Add EF tools to PATH
run: echo "$HOME/.dotnet/tools" >> $GITHUB_PATH
- name: Generate EF migration bundle
run: |
dotnet ef migrations bundle \
--project ${{ env.WEB_PROJECT }} \
--output efbundle.exe \
--configuration ${{ env.BUILD_CONFIGURATION }} \
--runtime ${{ env.RUNTIME_IDENTIFIER }} \
--context AdminDbContext \
env:
AdminSite__ConnectionString: ${{ secrets.PROD_SQL_CONNECTIONSTRING }}
- name: Run EF migration bundle
run: |
./efbundle.exe
env:
AdminSite__ConnectionString: ${{ secrets.PROD_SQL_CONNECTIONSTRING }}
De bundel leest verbindingsstrings van omgevingsvariabelen en past in afwachting van migraties toe. Reeds toegepast? Het sluit gewoon succesvol af.
Geen CI? Wilt u testen voordat u duwt? Bouw bundels lokaal.
Gebruiks gevallen: Test vóór CI, DBA-handoff (zelfingesloten exe, geen SDK nodig), ensceneringen, debuggen met --verbose.
# Install EF CLI (once)
dotnet tool install --global dotnet-ef
# Basic bundle
dotnet ef migrations bundle \
--project Mostlylucid.DbContext \
--startup-project Mostlylucid \
--output efbundle.exe
# Self-contained (includes runtime - portable to machines without .NET)
dotnet ef migrations bundle \
--project Mostlylucid.DbContext \
--startup-project Mostlylucid \
--output efbundle.exe \
--self-contained
# Cross-platform (e.g., build on Windows, deploy to Linux)
dotnet ef migrations bundle \
--project Mostlylucid.DbContext \
--startup-project Mostlylucid \
--output efbundle \
--runtime linux-x64
# Using default connection string from appsettings.json
./efbundle.exe
# Override with a specific connection string
./efbundle.exe --connection "Host=localhost;Database=mostlylucid;Username=postgres;Password=secret"
# Using an environment variable (matches your config key)
$env:ConnectionStrings__DefaultConnection="Host=localhost;..." # PowerShell
export ConnectionStrings__DefaultConnection="Host=localhost;..." # Bash
./efbundle.exe
# See what migrations would be applied without running them
./efbundle.exe --dry-run
# Verbose output for debugging
./efbundle.exe --verbose
# Apply migrations up to a specific migration (useful for testing)
./efbundle.exe --target-migration "20231115_AddUserTable"
# Combine options
./efbundle.exe --verbose --dry-run
# 1. Create migration
dotnet ef migrations add AddNewFeature \
--project Mostlylucid.DbContext \
--startup-project Mostlylucid
# 2. Build bundle
dotnet ef migrations bundle \
--project Mostlylucid.DbContext \
--startup-project Mostlylucid \
--output efbundle.exe
# 3. Dry run first
./efbundle.exe --dry-run --verbose
# 4. Run for real
./efbundle.exe --verbose
# 5. Broken? Remove and retry
dotnet ef migrations remove \
--project Mostlylucid.DbContext \
--startup-project Mostlylucid
Vangst syntaxis fouten, beperkingen schendingen, FK problemen - alle voor CI of productie.
Bundelgeneratie is traag - 30+ seconden op grote projecten. Niet genereren op elk gebouw.
Als je echt auto-generatie wilt, voeg dan een MSBuild target toe:
<Target Name="BuildMigrationBundle">
<Exec Command="dotnet ef migrations bundle --output $(OutputPath)efbundle.exe --force" />
</Target>
Dan: dotnet build -t:BuildMigrationBundle
Beste van beide werelden: gemak lokaal, veiligheid in de productie.
if (builder.Environment.IsDevelopment())
{
using var scope = app.Services.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<IMostlylucidDBContext>();
await context.Database.MigrateAsync();
}
// Production: CI pipeline runs the bundle
Genereer gewone SQL in plaats van een uitvoerbaar programma. Geweldig voor DBA-evaluatie en bestaande veranderingsbeheerprocessen.
# All migrations
dotnet ef migrations script --output migrations.sql
# Idempotent (safe to run multiple times) - USE THIS
dotnet ef migrations script --idempotent --output migrations.sql
# Range of migrations
dotnet ef migrations script FromMigration ToMigration --output migrations.sql
Voordelen: Volledige zichtbaarheid, elke SQL client kan uitvoeren, versie controle vriendelijk, DBA goedkeuring workflows.
Nadelen: Geen auto-tracking (gebruik --idempotent), handmatige uitvoering, potentiële drift als scripts worden gewijzigd.
Zie officiële documenten over SQL-scripts.
- name: Generate and apply migrations
run: |
dotnet ef migrations script --idempotent --output migrations.sql
# SQL Server
sqlcmd -S ${{ secrets.DB_SERVER }} -d ${{ secrets.DB_NAME }} -i migrations.sql
# Or PostgreSQL
PGPASSWORD=${{ secrets.DB_PASSWORD }} psql -h ${{ secrets.DB_HOST }} -f migrations.sql
DACCAC's zijn state-based niet migratie-gebaseerd. U definieert het gewenste schema, en SqlPackage diffeert het met de doeldatabase.
SqlPackage.exe /Action:Publish /SourceFile:MyDatabase.dacpac /TargetConnectionString:"..."
Voordelen: Schema als code, auto-diff generatie, behandelt alles (tabellen, weergaven, SP's, indexen), enterprise tooling.
Nadelen: SQL Server alleen, schema op twee plaatsen (EF-modellen + SQL project), diff engine maakt twijfelachtige keuzes, kolomhernoemingen lijken op drop+add.
Zie SqlPackage docs.
Aanpak Best Voor .NET vereist Auto-tracks Toegepast DBA Vriendelijk Cross-platform DB
|----------|----------|---------------|---------------------|--------------|-------------------|
| MigrateAsync() Dev/kleine projecten Ja (runtime) Ja
EF-bundels - CI/CD-pijpleidingen - Nee (zelfvoorzienend) - Ja -- Ja -- Ja -- Ja
SQL Scripts DBA-gecontroleerde omgevingen --idempotent Ja Ja Ja
DACAC SQL Server enterprise Nee Ja (state-based) Ja Nee
Migratie werkt lokaal, maar niet in CI? Controleer of je beide bestanden hebt vastgelegd:
20231115_AddUserTable.cs - De migratiecode.20231115_AddUserTable.Designer.cs - De model snapshotOntbreken van het Designer bestand = stil falen.
dotnet ef migrations bundle --context BlogDbContext --output blog-migrations.exe
dotnet ef migrations bundle --context IdentityDbContext --output identity-migrations.exe
--connection argumentappsettings.jsonGebruik omgevingsvariabelen in CI.
EF-tools moeten uw DbContext instantiëren. Als uw DbContext in een apart project zit of complexe opstart heeft, implementeren IDesignTimeDbContextFactory<T>:
public class AdminDbContextFactory : IDesignTimeDbContextFactory<AdminDbContext>
{
public AdminDbContext CreateDbContext(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true)
.AddEnvironmentVariables()
.AddUserSecrets<AdminDbContextFactory>()
.Build();
var connectionString = config["AdminSite:ConnectionString"]
?? throw new InvalidOperationException("Missing connection string");
var optionsBuilder = new DbContextOptionsBuilder<AdminDbContext>();
optionsBuilder.UseSqlServer(connectionString, sql => sql.CommandTimeout(120));
return new AdminDbContext(optionsBuilder.Options);
}
}
Gebruik wanneer: DbContext in apart project, complexe opstart, User Secrets nodig hebben voor ontwerp-tijd.
Veelgestelde vragen en terugval die ik heb ontvangen.
dotnet ef database update in CI?"Overdekt boven, maar de korte versie: bundels zijn draagbare artefacten. Uw implementatie stap hoeft niet EF CLI, broncode, of ontwerp-tijd resolutie. Dezelfde bundel draait in test, enscenering, en prod - nul drift.
Als je alleen bent, is de data openbaar en is de straal laag... MigrateAsync() Maar zodra je een tweede ontwikkelaar, gevoelige gegevens of meerdere omgevingen toevoegt, betalen bundels voor zichzelf.
EF doet geen automatische terugrol. Opties:
Down() migratie en voer het uit (maar je moet het hebben geschreven)Voor kritieke systemen: eerst de migratie testen op een databasekloon.
Ja. Bundel + init container is een solide patroon:
initContainers:
- name: migrate
image: myapp:latest
command: ["./efbundle.exe"]
env:
- name: ConnectionStrings__Default
valueFrom:
secretKeyRef:
name: db-secrets
key: connection-string
App container wacht tot init klaar is.
Ze werken geweldig. EF bundels zijn de EF-native oplossing, maar FluentMigrator en DbUp belangrijk verschil: dat zijn migratie-specifieke tools, terwijl EF-bundels afkomstig zijn van uw bestaande EF-model.
Gebruik --idempotent scripts:
dotnet ef migrations script --idempotent --output migrations.sql
DBA beoordelingen en keurt het goed.
Dat is een inzet strategie vraag, geen migratie vraag.
Bundels lossen dit niet op - ze maken stap 3 gewoon voorspelbaarer.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.