Migraties toepassen
Zodra uw migraties zijn toegevoegd, moeten ze worden geïmplementeerd en toegepast op uw databases. Er zijn verschillende strategieën om dit te doen, waarbij sommige beter geschikt zijn voor productieomgevingen en andere voor de ontwikkelingslevenscyclus.
Notitie
Ongeacht uw implementatiestrategie controleert u altijd de gegenereerde migraties en test u deze voordat u deze toepast op een productiedatabase. Een migratie kan een kolom verwijderen wanneer de naam van de kolom is gewijzigd of kan om verschillende redenen mislukken wanneer deze wordt toegepast op een database.
SQL scripts
De aanbevolen manier om migraties naar een productiedatabase te implementeren, is door SQL-scripts te genereren. De voordelen van deze strategie zijn onder andere:
- SQL-scripts kunnen worden gecontroleerd op nauwkeurigheid; dit is belangrijk omdat het toepassen van schemawijzigingen op productiedatabases een potentieel gevaarlijke bewerking is waarbij gegevens verloren kunnen gaan.
- In sommige gevallen kunnen de scripts worden afgestemd op de specifieke behoeften van een productiedatabase.
- SQL-scripts kunnen worden gebruikt in combinatie met een implementatietechnologie en kunnen zelfs worden gegenereerd als onderdeel van uw CI-proces.
- SQL-scripts kunnen worden verstrekt aan een DBA en kunnen afzonderlijk worden beheerd en gearchiveerd.
Basisgebruik
Hieronder wordt een SQL-script gegenereerd van een lege database naar de meest recente migratie:
dotnet ef migrations script
Met "van naar" (impliciet)
Hieronder wordt een SQL-script gegenereerd van de opgegeven migratie naar de meest recente migratie.
dotnet ef migrations script AddNewTables
Met 'Van' en 'Naar'
Hieronder wordt een SQL-script gegenereerd van de opgegeven from
migratie naar de opgegeven to
migratie.
dotnet ef migrations script AddNewTables AddAuditTable
U kunt een from
gebruiken die nieuwer is dan de to
om een terugdraaiscript te genereren.
Waarschuwing
Noteer mogelijke scenario's voor gegevensverlies.
Het genereren van scripts accepteert de volgende twee argumenten om aan te geven welk bereik van migraties moet worden gegenereerd:
- De van migratie moet de laatste migratie zijn die op de database is toegepast voordat het script wordt uitgevoerd. Als er geen migraties zijn toegepast, geeft u
0
op (dit is de standaardinstelling). - De voor migratie is de laatste migratie die wordt toegepast op de database nadat het script is uitgevoerd. Dit wordt standaard ingesteld op de laatste migratie in uw project.
Idempotent SQL-scripts
De hierboven gegenereerde SQL-scripts kunnen alleen worden toegepast om uw schema te wijzigen van de ene migratie naar de andere; het is uw verantwoordelijkheid om het script op de juiste manier toe te passen en alleen op databases met de juiste migratiestatus. EF Core ondersteunt ook het genereren van idempotent scripts, die intern controleren welke migraties al zijn toegepast (via de geschiedenistabel van migraties) en alleen ontbrekende scripts toepassen. Dit is handig als u niet precies weet wat de laatste migratie is die op de database is toegepast, of als u implementeert in meerdere databases die mogelijk bij een andere migratie zijn.
Met het volgende worden idempotente migraties gegenereerd:
dotnet ef migrations script --idempotent
Opdrachtregelprogramma's
De EF-opdrachtregelprogramma's kunnen worden gebruikt om migraties toe te passen op een database. Hoewel u productief bent voor lokale ontwikkeling en het testen van migraties, is deze benadering niet ideaal voor het beheren van productiedatabases:
- De SQL-opdrachten worden rechtstreeks door het hulpprogramma toegepast, zonder dat de ontwikkelaar deze kan inspecteren of wijzigen. Dit kan gevaarlijk zijn in een productieomgeving.
- De .NET SDK en het EF-hulpprogramma moeten worden geïnstalleerd op productieservers en vereist de broncode van het project.
Met de volgende updates wordt uw database bijgewerkt naar de nieuwste migratie:
dotnet ef database update
Met de volgende updates wordt uw database bijgewerkt naar een bepaalde migratie:
dotnet ef database update AddNewTables
Houd er rekening mee dat dit ook kan worden gebruikt om terug te keren naar een eerdere migratie.
Waarschuwing
Noteer mogelijke scenario's voor gegevensverlies.
Zie de EF Core-hulpprogramma'svoor meer informatie over het toepassen van migraties via de opdrachtregelprogramma's.
Bundels
Migratiebundels zijn uitvoerbare bestanden met één bestand die kunnen worden gebruikt om migraties toe te passen op een database. Ze pakken enkele van de tekortkomingen van het SQL-script en opdrachtregelprogramma's aan:
- Voor het uitvoeren van SQL-scripts zijn extra hulpprogramma's vereist.
- De transactieafhandeling en het doorgaan-bij-fouten gedrag van deze hulpprogramma's zijn inconsistent en soms onverwacht. Hierdoor kan uw database een niet-gedefinieerde status hebben als er een fout optreedt bij het toepassen van migraties.
- Bundels kunnen worden gegenereerd als onderdeel van uw CI-proces en kunnen later eenvoudig worden uitgevoerd als onderdeel van uw implementatieproces.
- Bundels kunnen worden uitgevoerd zonder de .NET SDK of HET EF-hulpprogramma te installeren (of zelfs de .NET Runtime, als deze zelfstandig is) en ze hebben de broncode van het project niet nodig.
Met het volgende wordt een bundel gegenereerd:
dotnet ef migrations bundle
Met het volgende wordt een zelfstandige bundel voor Linux gegenereerd:
dotnet ef migrations bundle --self-contained -r linux-x64
Raadpleeg de EF Core-hulpprogramma'svoor meer informatie over het maken van bundels.
efbundle
Het resulterende uitvoerbare bestand heet standaard efbundle
. Deze kan worden gebruikt om de database bij te werken naar de meest recente migratie. Het is gelijk aan het uitvoeren van dotnet ef database update
of Update-Database
.
Argumenten:
Argument | Beschrijving |
---|---|
<MIGRATION> |
De doelmigratie. Als de waarde '0' is, worden alle migraties teruggezet. Standaard ingesteld op de laatste migratie. |
Opties:
Optie | Kort | Beschrijving |
---|---|---|
--connection <CONNECTION> |
De verbindingsreeks voor de database. Standaard ingesteld op de waarde die is opgegeven in AddDbContext of OnConfiguring. | |
--verbose |
-v |
Uitgebreide uitvoer weergeven. |
--no-color |
Kleur de uitvoer niet. | |
--prefix-output |
Voorzie de uitvoer van een voorvoegsel met niveau. |
In het volgende voorbeeld worden migraties toegepast op een lokaal SQL Server-exemplaar met behulp van de opgegeven gebruikersnaam en referenties:
.\efbundle.exe --connection 'Data Source=(local)\MSSQLSERVER;Initial Catalog=Blogging;User ID=myUsername;Password={;'$Credential;'here'}'
Waarschuwing
Vergeet niet om appsettings.json naast je bundel te kopiëren. De bundel is afhankelijk van de aanwezigheid van appsettings.json in de uitvoermap.
Voorbeeld van migratiebundel
Voor een bundel moeten migraties worden opgenomen. Deze worden gemaakt met behulp van dotnet ef migrations add
zoals beschreven in Uw eerste migratie maken. Zodra u migraties klaar hebt om te implementeren, maakt u een bundel met behulp van de dotnet ef migrations bundle
. Bijvoorbeeld:
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>
De uitvoer is een uitvoerbaar bestand dat geschikt is voor het beoogde besturingssysteem. In mijn geval is dit Windows x64, dus ik krijg een efbundle.exe
gedropt in mijn lokale map. Als u dit uitvoerbare bestand uitvoert, worden de migraties hierin toegepast:
PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903083845_MyMigration'.
Done.
PS C:\local\AllTogetherNow\SixOh>
Net als bij dotnet ef database update
of Update-Database
worden migraties alleen toegepast op de database als ze nog niet zijn toegepast. Als u dezelfde bundel bijvoorbeeld opnieuw uitvoert, gebeurt er niets, omdat er geen nieuwe migraties zijn die moeten worden toegepast:
PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
No migrations were applied. The database is already up to date.
Done.
PS C:\local\AllTogetherNow\SixOh>
Als er echter wijzigingen worden aangebracht in het model en er meer migraties worden gegenereerd met dotnet ef migrations add
, kunnen deze worden gebundeld in een nieuw uitvoerbaar bestand dat kan worden toegepast. Bijvoorbeeld:
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>
Fooi
De optie --force
kan worden gebruikt om de bestaande bundel te overschrijven met een nieuwe bundel.
Als u deze nieuwe bundel uitvoert, worden deze twee nieuwe migraties toegepast op de database:
PS C:\local\AllTogetherNow\SixOh> .\efbundle.exe
Applying migration '20210903084526_SecondMigration'.
Applying migration '20210903084538_Number3'.
Done.
PS C:\local\AllTogetherNow\SixOh>
De bundel maakt standaard gebruik van de databaseverbindingsreeks uit de configuratie van uw toepassing. Een andere database kan echter worden gemigreerd door de verbindingsreeks op de opdrachtregel door te geven. Bijvoorbeeld:
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>
Notitie
Deze keer werden alle drie de migraties toegepast, omdat ze nog niet waren toegepast op de productiedatabase.
Migraties tijdens runtime toepassen
Het is mogelijk dat de toepassing zelf programmatisch migraties toepast, meestal tijdens het opstarten. Hoewel ze productief zijn voor lokale ontwikkeling en het testen van migraties, is deze aanpak om de volgende redenen niet geschikt voor het beheren van productiedatabases:
- Voor versies van EF vóór 9, als er meerdere exemplaren van uw toepassing worden uitgevoerd, kunnen beide toepassingen proberen de migratie gelijktijdig toe te passen en te mislukken (of erger, leiden tot beschadiging van gegevens).
- Als een toepassing toegang heeft tot de database terwijl een andere toepassing deze migreert, kan dit ernstige problemen veroorzaken.
- De toepassing moet verhoogde toegang hebben om het databaseschema te wijzigen. Het is over het algemeen een goede gewoonte om de databasemachtigingen van de toepassing in productie te beperken.
- Het is belangrijk om een toegepaste migratie terug te draaien in geval van een probleem. De andere strategieën bieden dit gemakkelijk en kant-en-klare.
- De SQL-opdrachten worden rechtstreeks door het programma toegepast, zonder de ontwikkelaar de kans te geven om ze te inspecteren of te wijzigen. Dit kan gevaarlijk zijn in een productieomgeving.
Als u migraties programmatisch wilt toepassen, roept u context.Database.MigrateAsync()
aan. Een typische ASP.NET toepassing kan bijvoorbeeld het volgende doen:
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();
}
Houd er rekening mee dat MigrateAsync()
is gebaseerd op de IMigrator
-service, die kan worden gebruikt voor geavanceerdere scenario's. Gebruik myDbContext.GetInfrastructure().GetService<IMigrator>()
om er toegang toe te krijgen.
Waarschuwing
- Overweeg zorgvuldig voordat u deze benadering in productie gebruikt. De ervaring heeft aangetoond dat de eenvoud van deze implementatiestrategie minder zwaar weegt dan de problemen die het veroorzaakt. U kunt in plaats daarvan SQL-scripts genereren op basis van migraties.
- Bel
EnsureCreatedAsync()
niet voorMigrateAsync()
.EnsureCreatedAsync()
migraties omzeilt om het schema te maken, waardoorMigrateAsync()
mislukt.