Gestione delle migrazioni
Man mano che il modello cambia, le migrazioni vengono aggiunte e rimosse durante lo sviluppo normale e i file di migrazione vengono controllati nel controllo del codice sorgente del progetto. Per gestire le migrazioni, è prima necessario installare gli strumenti da riga di comando di EF Core .
Suggerimento
Se il DbContext
si trova in un assembly diverso rispetto al progetto di avvio, è possibile specificare in modo esplicito i progetti di destinazione e avvio negli strumenti della console di Gestione pacchetti o negli strumenti dell'interfaccia della riga di comando di .NET Core .
Aggiungere una migrazione
Dopo aver modificato il modello, è possibile aggiungere una migrazione per tale modifica:
dotnet ef migrations add AddBlogCreatedTimestamp
Il nome della migrazione può essere usato come un messaggio di commit in un sistema di controllo della versione. Ad esempio, è possibile scegliere un nome come AddBlogCreatedTimestamp se la modifica è una nuova proprietà CreatedTimestamp
nell'entità Blog
.
Tre file sono stati aggiunti al progetto nella directory Migrations:
-
XXXXXXXXXXXXXX_AddBlogCreatedTimestamp.cs: file delle migrazioni principale. Contiene le operazioni necessarie per applicare la migrazione (in
Up
) e per ripristinarla (inDown
). - XXXXXXXXXXXXXX_AddBlogCreatedTimestamp.Designer.cs--File di metadati delle migrazioni. Contiene informazioni usate da Entity Framework.
- MyContextModelSnapshot.cs--Uno snapshot del modello corrente. Usato per determinare le modifiche apportate durante l'aggiunta della migrazione successiva.
Il timestamp nel nome file consente di mantenerli ordinati in ordine cronologico in modo da visualizzare la progressione delle modifiche.
Namespace
Avete la libertà di spostare manualmente i file delle migrazioni e modificarne lo spazio dei nomi. Le nuove migrazioni vengono create come migrazioni di pari livello rispetto all'ultima migrazione. In alternativa, è possibile specificare la directory in fase di generazione come indicato di seguito:
dotnet ef migrations add InitialCreate --output-dir Your/Directory
Nota
È anche possibile modificare lo spazio dei nomi indipendentemente dalla directory usando --namespace
.
Personalizzare il codice di migrazione
Mentre EF Core crea in genere migrazioni accurate, è consigliabile esaminare sempre il codice e assicurarsi che corrisponda alla modifica desiderata; in alcuni casi, è anche necessario farlo.
Rinomina delle colonne
Un esempio importante in cui è necessaria la personalizzazione delle migrazioni è la ridenominazione di una proprietà. Ad esempio, se si rinomina una proprietà da Name
a FullName
, EF Core genererà la migrazione seguente:
migrationBuilder.DropColumn(
name: "Name",
table: "Customers");
migrationBuilder.AddColumn<string>(
name: "FullName",
table: "Customers",
nullable: true);
EF Core in genere non è in grado di sapere quando l'intenzione è eliminare una colonna e crearne una nuova (due modifiche separate) e quando una colonna deve essere rinominata. Se la migrazione precedente viene applicata as-is, tutti i nomi dei clienti andranno persi. Per rinominare una colonna, sostituire la migrazione generata in precedenza con quanto segue:
migrationBuilder.RenameColumn(
name: "Name",
table: "Customers",
newName: "FullName");
Suggerimento
Il processo di scaffolding della migrazione avvisa quando un'operazione potrebbe comportare una perdita di dati, ad esempio l'eliminazione di una colonna. Se viene visualizzato l'avviso, assicurarsi in particolare di esaminare il codice delle migrazioni per verificare l'accuratezza.
Aggiunta di SQL non elaborato
Anche se la ridenominazione di una colonna può essere ottenuta tramite un'API predefinita, in molti casi non è possibile. Ad esempio, è possibile sostituire le proprietà FirstName
e LastName
esistenti con una singola proprietà FullName
. La migrazione generata da EF Core sarà la seguente:
migrationBuilder.DropColumn(
name: "FirstName",
table: "Customer");
migrationBuilder.DropColumn(
name: "LastName",
table: "Customer");
migrationBuilder.AddColumn<string>(
name: "FullName",
table: "Customer",
nullable: true);
Come in precedenza, ciò causerebbe una perdita di dati indesiderata. Per trasferire i dati dalle colonne precedenti, vengono riorganizzare le migrazioni e introdurre un'operazione SQL non elaborata come indicato di seguito:
migrationBuilder.AddColumn<string>(
name: "FullName",
table: "Customer",
nullable: true);
migrationBuilder.Sql(
@"
UPDATE Customer
SET FullName = FirstName + ' ' + LastName;
");
migrationBuilder.DropColumn(
name: "FirstName",
table: "Customer");
migrationBuilder.DropColumn(
name: "LastName",
table: "Customer");
Modifiche arbitrarie tramite SQL non elaborato
SQL non elaborato può essere usato anche per gestire gli oggetti di database di cui EF Core non è a conoscenza. A tale scopo, aggiungere una migrazione senza apportare alcuna modifica al modello; verrà generata una migrazione vuota, che sarà quindi possibile popolare con operazioni SQL non elaborate.
Ad esempio, la migrazione seguente crea una stored procedure di SQL Server:
migrationBuilder.Sql(
@"
EXEC ('CREATE PROCEDURE getFullName
@LastName nvarchar(50),
@FirstName nvarchar(50)
AS
RETURN @LastName + @FirstName;')");
Suggerimento
EXEC
viene usato quando un'istruzione deve essere la prima o una sola in un batch SQL. Può anche essere usato per risolvere gli errori del parser negli script di migrazione idempotenti che possono verificarsi quando le colonne a cui si fa riferimento non esistono attualmente in una tabella.
Può essere usato per gestire qualsiasi aspetto del database, tra cui:
- Procedure memorizzate
- Ricerca testo integrale
- Funzioni
- Triggeri
- Visualizzazioni
Nella maggior parte dei casi, EF Core racchiude automaticamente ogni migrazione nella propria transazione quando si applicano le migrazioni. Sfortunatamente, alcune operazioni di migrazione non possono essere eseguite all'interno di una transazione in alcuni database; per questi casi, è possibile rifiutare esplicitamente la transazione passando suppressTransaction: true
a migrationBuilder.Sql
.
Rimuovere una migrazione
A volte si aggiunge una migrazione e ci si rende conto che è necessario apportare altre modifiche al modello di EF Core prima di applicarla. Per rimuovere l'ultima migrazione, usare questo comando.
dotnet ef migrations remove
Dopo aver rimosso la migrazione, è possibile apportare le modifiche aggiuntive del modello e aggiungerlo di nuovo.
Avvertimento
Evitare di rimuovere eventuali migrazioni già applicate ai database di produzione. In questo modo non sarà possibile ripristinare tali migrazioni nei database e potrebbe compromettere i presupposti fatti dalle migrazioni successive.
Elenco delle migrazioni
È possibile elencare tutte le migrazioni esistenti come indicato di seguito:
dotnet ef migrations list
Controllo delle modifiche al modello in sospeso
Nota
Questa funzionalità è stata aggiunta in EF Core 8.0.
In alcuni casi potrebbe essere necessario verificare se sono state apportate modifiche al modello dall'ultima migrazione. Questo può aiutarti a sapere quando tu o un compagno di squadra vi siete dimenticati di aggiungere una migrazione. Un modo per eseguire questa operazione consiste nell'usare questo comando.
dotnet ef migrations has-pending-model-changes
È anche possibile eseguire questo controllo a livello di codice usando context.Database.HasPendingModelChanges()
. Può essere usato per scrivere un test unità che fallisce se si dimentica di aggiungere una migrazione.
Reimpostazione di tutte le migrazioni
In alcuni casi estremi potrebbe essere necessario rimuovere tutte le migrazioni e ricominciare. Questa operazione può essere eseguita facilmente eliminando la cartella Migrations e rilasciando il database; a questo punto è possibile creare una nuova migrazione iniziale, che conterrà l'intero schema corrente.
È anche possibile reimpostare tutte le migrazioni e crearne una singola senza perdere i dati. Questa operazione è talvolta denominata "squashing" e comporta alcune operazioni manuali:
- Eseguire il backup del database, nel caso in cui si sia verificato un errore.
- Nel database eliminare tutte le righe dalla tabella della cronologia delle migrazioni, ad esempio
DELETE FROM [__EFMigrationsHistory]
in SQL Server. - Elimina la cartella Migrations.
- Creare una nuova migrazione e generarne uno script SQL (
dotnet ef migrations script
). - Inserire una singola riga nella cronologia delle migrazioni per registrare che la prima migrazione è già stata applicata, poiché le tabelle sono già presenti. L'istruzione SQL di inserimento è l'ultima operazione nello script SQL generato in precedenza e è simile alla seguente (non dimenticare di aggiornare i valori):
INSERT INTO [__EFMigrationsHistory] ([MIGRATIONID], [PRODUCTVERSION])
VALUES (N'<full_migration_timestamp_and_name>', N'<EF_version>');
Avvertimento
Qualsiasi codice di migrazione personalizzato andrà perso quando viene eliminata la cartella Migrazioni. Per conservare le eventuali personalizzazioni, è necessario applicare manualmente la nuova migrazione iniziale.
Risorse aggiuntive
- informazioni di riferimento sugli strumenti di Entity Framework Core - Interfaccia della riga di comando di .NET Core : include comandi per aggiornare, eliminare, aggiungere, rimuovere e altro ancora.
- Informazioni di riferimento sugli strumenti di Entity Framework Core - Console di Gestione Pacchetti in Visual Studio: Comprende i comandi per aggiornare, eliminare, aggiungere, rimuovere e altro ancora.