Dela via


Tillämpa migreringar

När dina migreringar har lagts till måste de distribueras och tillämpas på dina databaser. Det finns olika strategier för att göra detta, där vissa är mer lämpliga för produktionsmiljöer och andra för utvecklingslivscykeln.

Anteckning

Oavsett distributionsstrategi kontrollerar du alltid de genererade migreringarna och testar dem innan du tillämpar dem på en produktionsdatabas. En migrering kan släppa en kolumn när avsikten var att byta namn på den, eller misslyckas av olika skäl när den tillämpas på en databas.

SQL-skript

Det rekommenderade sättet att distribuera migreringar till en produktionsdatabas är genom att generera SQL-skript. Fördelarna med den här strategin är följande:

  • SQL-skript kan granskas för noggrannhet. Detta är viktigt eftersom det är en potentiellt farlig åtgärd att tillämpa schemaändringar på produktionsdatabaser som kan innebära dataförlust.
  • I vissa fall kan skripten justeras så att de passar de specifika behoven i en produktionsdatabas.
  • SQL-skript kan användas tillsammans med en distributionsteknik och kan även genereras som en del av din CI-process.
  • SQL-skript kan tillhandahållas till en DBA och kan hanteras och arkiveras separat.

Grundläggande användning

Följande genererar ett SQL-skript från en tom databas till den senaste migreringen:

dotnet ef migrations script

Från (till underförstått)

Följande genererar ett SQL-skript från den angivna migreringen till den senaste migreringen.

dotnet ef migrations script AddNewTables

Från och Till

Följande genererar ett SQL-skript från den angivna from migreringen till den angivna to migreringen.

dotnet ef migrations script AddNewTables AddAuditTable

Du kan använda en from som är nyare än to för att generera ett återställningsskript.

Varning

Observera potentiella dataförlustscenarier.

Skriptgenereringen accepterar följande två argument för att ange vilket migreringsintervall som ska genereras:

  • Migreringen från till ska vara den sista som tillämpas på databasen innan skriptet körs. Om inga migreringar har tillämpats anger du 0 (detta är standardvärdet).
  • Migreringen från till är den sista migreringen som ska tillämpas på databasen efter att skriptet har körts. Detta är standardinställningen för den senaste migreringen i projektet.

Idempotent SQL-skript

SQL-skripten som genereras ovan kan bara användas för att ändra schemat från en migrering till en annan. det är ditt ansvar att tillämpa skriptet på rätt sätt och endast på databaser i rätt migreringstillstånd. EF Core stöder också generering av idempotenta skript, som internt kontrollerar vilka migreringar som redan har tillämpats (via tabellen med migreringshistorik) och endast tillämpar saknade. Det här är användbart om du inte exakt vet vad den senaste migreringen som tillämpades på databasen var, eller om du distribuerar till flera databaser som var och en kan ha en annan migrering.

Följande genererar idempotenta migreringar:

dotnet ef migrations script --idempotent

Kommandoradsverktyg

Ef-kommandoradsverktygen kan användas för att tillämpa migreringar på en databas. Även om den här metoden är produktiv för lokal utveckling och testning av migreringar är den inte idealisk för att hantera produktionsdatabaser:

  • SQL-kommandona tillämpas direkt av verktyget, utan att ge utvecklaren en chans att inspektera eller ändra dem. Detta kan vara farligt i en produktionsmiljö.
  • .NET SDK och EF-verktyget måste installeras på produktionsservrar och kräver projektets källkod.

Följande uppdaterar databasen till den senaste migreringen:

dotnet ef database update

Följande uppdaterar databasen till en angiven migrering:

dotnet ef database update AddNewTables

Observera också att detta kan användas för att gå tillbaka till en tidigare migrering.

Varning

Observera potentiella dataförlustscenarier.

Mer information om hur du tillämpar migreringar via kommandoradsverktygen finns i referensen EF Core-verktyg.

Buntar

Migreringspaket är exekverbara filer i en enda fil som kan användas för att tillämpa migreringar på en databas. De åtgärdar några av bristerna i SQL-skriptet och kommandoradsverktygen:

  • För att köra SQL-skript krävs ytterligare verktyg.
  • Beteendet för transaktionshantering och fortsätta vid fel för dessa verktyg är inkonsekvent och ibland oväntat. Detta kan lämna databasen i ett odefinierat tillstånd om ett fel inträffar vid tillämpning av migreringar.
  • Paket kan genereras som en del av din CI-process och enkelt köras senare som en del av distributionsprocessen.
  • Paket kan köras utan att installera .NET SDK eller EF Tool (eller till och med .NET Runtime, när de är fristående) och de kräver inte projektets källkod.

Följande genererar ett paket:

dotnet ef migrations bundle

Följande genererar ett fristående paket för Linux:

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

Mer information om hur du skapar paket finns i referensen EF Core-verktyg.

efbundle

Den resulterande körbara filen heter efbundle som standard. Den kan användas för att uppdatera databasen till den senaste migreringen. Det motsvarar att köra dotnet ef database update eller Update-Database.

Argument:

Argument Beskrivning
<MIGRATION> Mål för migrering. Om "0" återställs alla migreringar. Standardinställningen är den sist utförda migreringen.

Alternativ:

Alternativ Kort Beskrivning
--connection <CONNECTION> Anslutningssträngen till databasen. Använder standardinställningen som anges i AddDbContext eller OnConfiguring.
--verbose -v Visa utförliga utdata.
--no-color Färglägga inte utdata.
--prefix-output Prefixutdata med nivå.

I följande exempel tillämpas migreringar på en lokal SQL Server-instans med det angivna användarnamnet och autentiseringsuppgifterna:

.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password={;'$Credential;'here'}'

Varning

Glöm inte att kopiera appsettings.json tillsammans med ditt paket. Paketet förlitar sig på förekomsten av appsettings.json i exekveringskatalogen.

Exempel på migreringspaket

Ett paket behöver inkludera migreringar. Dessa skapas med hjälp av dotnet ef migrations add enligt beskrivningen i Skapa din första migrering. När du har migreringar redo att distribueras skapar du ett paket med hjälp av dotnet ef migrations bundle. Till exempel:

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>

Utdata är en körbar fil som passar ditt måloperativsystem. I min situation är detta Windows x64, så jag får en efbundle.exe placerad i min lokala mapp. Att köra denna körbara fil tillämpar de migreringar som finns i den.

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

Precis som med dotnet ef database update eller Update-Databasetillämpas migreringar endast på databasen om de inte redan har tillämpats. Att köra samma paket igen gör till exempel ingenting, eftersom det inte finns några nya migreringar att tillämpa:

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

Men om ändringar görs i modellen och fler migreringar genereras med dotnet ef migrations addkan dessa paketeras till en ny körbar fil som är redo att tillämpas. Till exempel:

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>

Tips

Alternativet --force kan användas för att skriva över det befintliga paketet med ett nytt.

När du kör det här nya paketet tillämpas dessa två nya migreringar på databasen:

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

Som standard använder paketet databasanslutningssträngen från programmets konfiguration. En annan databas kan dock migreras genom att skicka anslutningssträngen på kommandoraden. Till exempel:

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>

Anteckning

Den här gången tillämpades alla tre migreringarna, eftersom ingen av dem ännu hade tillämpats på produktionsdatabasen.


Tillämpa migreringar vid körning

Det är möjligt för själva programmet att tillämpa migreringar programmatiskt, vanligtvis under start. Även om den här metoden är produktiv för lokal utveckling och testning av migreringar är den olämplig för hantering av produktionsdatabaser av följande skäl:

  • Om flera instanser av ditt program körs för versioner av EF före 9 kan båda programmen försöka tillämpa migreringen samtidigt och misslyckas (eller ännu värre, orsaka skada på data).
  • På samma sätt kan detta orsaka allvarliga problem om ett program kommer åt databasen medan ett annat program migrerar den.
  • Programmet måste ha förhöjd åtkomst för att ändra databasschemat. Det är vanligtvis bra att begränsa programmets databasbehörigheter i produktion.
  • Det är viktigt att kunna återställa en tillämpad migrering i händelse av ett problem. De andra strategierna ger detta enkelt och utan krångel.
  • SQL-kommandona tillämpas direkt av programmet, utan att ge utvecklaren en chans att inspektera eller ändra dem. Detta kan vara farligt i en produktionsmiljö.

Om du vill använda migreringar programmatiskt anropar du context.Database.MigrateAsync(). Ett typiskt ASP.NET program kan till exempel göra följande:

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

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

    host.Run();
}

Observera att MigrateAsync() bygger ovanpå IMigrator-tjänsten, som kan användas för mer avancerade scenarier. Använd myDbContext.GetInfrastructure().GetService<IMigrator>() för att komma åt den.

Varning

  • Överväg noggrant innan du använder den här metoden i produktion. Erfarenheten har visat att enkelheten i den här distributionsstrategin uppvägs av de problem som skapas. Överväg att generera SQL-skript från migreringar i stället.
  • Anropa inte EnsureCreatedAsync() innan MigrateAsync(). EnsureCreatedAsync() kringgår migreringar för att skapa schemat, vilket gör att MigrateAsync() misslyckas.