Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Di Tom Dykstra, Jon P Smith e Rick Anderson
L'app web di Contoso University dimostra come creare app Web Pages usando Razor e Visual Studio. Per informazioni sulla serie di esercitazioni, vedere la prima esercitazione.
Se si verificano problemi che non è possibile risolvere, scaricare l'app completata e confrontare tale codice con quello creato seguendo questa esercitazione.
Questa esercitazione presenta la EF Core funzionalità delle migrazioni per la gestione delle modifiche del modello di dati.
Quando viene sviluppata una nuova app, il modello di dati cambia frequentemente. Ogni volta che il modello cambia, il modello non viene sincronizzato con il database. La serie di esercitazioni inizia con la configurazione di Entity Framework per creare il database, se non esiste. Ogni volta che il modello di dati cambia, è necessario eliminare il database. Al successivo esecuzione dell'app, la chiamata a EnsureCreated crea nuovamente il database in modo che corrisponda al nuovo modello di dati. La DbInitializer classe viene quindi eseguita per eseguire il seeding del nuovo database.
Questo approccio per mantenere il database sincronizzato con il modello di dati funziona correttamente fino a quando l'app non deve essere distribuita nell'ambiente di produzione. Quando l'app è in esecuzione nell'ambiente di produzione, in genere archivia i dati che devono essere mantenuti. L'app non può iniziare con un database di test ogni volta che viene apportata una modifica, ad esempio l'aggiunta di una nuova colonna. La EF Core funzionalità Migrazioni risolve questo problema consentendo di EF Core aggiornare lo schema del database invece di creare un nuovo database.
Anziché eliminare e ricreare il database quando il modello di dati cambia, le migrazioni aggiornano lo schema e conservano i dati esistenti.
Annotazioni
Limitazioni di SQLite
Questa esercitazione usa la funzionalità Migrazioni di Entity Framework Core laddove possibile. Le migrazioni aggiornano lo schema del database in base alle modifiche nel modello di dati. Tuttavia, le migrazioni eseguono solo i tipi di modifiche supportate dal motore di database e le funzionalità di modifica dello schema di SQLite sono limitate. Ad esempio, l'aggiunta di una colonna è supportata, ma la rimozione di una colonna non è supportata. Se viene creata una migrazione per rimuovere una colonna, il ef migrations add comando ha esito positivo ma il ef database update comando ha esito negativo.
La soluzione per ovviare alle limitazioni di SQLite consiste nello scrivere manualmente il codice delle migrazioni per eseguire una ricompilazione della tabella in caso di modifiche nella tabella. Il codice viene inserito nei metodi Up e Down per una migrazione e implica:
- Creazione di una nuova tabella.
- Copia dei dati dalla vecchia tabella alla nuova tabella.
- Eliminazione della tabella precedente.
- Ridenominazione della nuova tabella.
La scrittura di codice specifico del database di questo tipo non rientra nell'ambito di questa esercitazione. Invece, questa esercitazione elimina e ricrea il database ogni volta che un tentativo di applicazione di una migrazione ha esito negativo. Per altre informazioni, vedere le risorse seguenti:
Eliminare il database
Usare Esplora oggetti di SQL Server (SSOX) per eliminare il database o eseguire il comando seguente nella console di Gestione pacchetti :USE SQL Server Object Explorer (SSOX) to delete the database, or run the following command in the Package Manager Console (PMC):
Drop-Database
Creare una migrazione iniziale
Eseguire i comandi seguenti nella console di Gestione pacchetti:
Add-Migration InitialCreate
Update-Database
Rimuovi EnsureCreated
Questa serie di esercitazioni è stata avviata usando EnsureCreated.
EnsureCreated non crea una tabella di cronologia delle migrazioni e quindi non può essere usata con le migrazioni. È progettato per il test o la creazione rapida di prototipi in cui il database viene eliminato e ricreato di frequente.
D'ora in avanti, i tutorial utilizzeranno le migrazioni.
In Program.cseliminare la riga seguente:
context.Database.EnsureCreated();
Eseguire l'app e verificare che il database sia sottoposto a seeding.
Metodi Up e Down
Codice EF Coremigrations add generato dal comando per creare il database. Questo codice di migrazione si trova nel Migrations\<timestamp>_InitialCreate.cs file . Il Up metodo della InitialCreate classe crea le tabelle di database che corrispondono ai set di entità del modello di dati. Il Down metodo li elimina, come illustrato nell'esempio seguente:
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace ContosoUniversity.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true),
Credits = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});
migrationBuilder.CreateTable(
name: "Student",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
LastName = table.Column<string>(nullable: true),
FirstMidName = table.Column<string>(nullable: true),
EnrollmentDate = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Student", x => x.ID);
});
migrationBuilder.CreateTable(
name: "Enrollment",
columns: table => new
{
EnrollmentID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
CourseID = table.Column<int>(nullable: false),
StudentID = table.Column<int>(nullable: false),
Grade = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Enrollment", x => x.EnrollmentID);
table.ForeignKey(
name: "FK_Enrollment_Course_CourseID",
column: x => x.CourseID,
principalTable: "Course",
principalColumn: "CourseID",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Enrollment_Student_StudentID",
column: x => x.StudentID,
principalTable: "Student",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Enrollment_CourseID",
table: "Enrollment",
column: "CourseID");
migrationBuilder.CreateIndex(
name: "IX_Enrollment_StudentID",
table: "Enrollment",
column: "StudentID");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Enrollment");
migrationBuilder.DropTable(
name: "Course");
migrationBuilder.DropTable(
name: "Student");
}
}
}
Il codice precedente è relativo alla migrazione iniziale. Codice:
- È stato generato dal
migrations add InitialCreatecomando . - Viene eseguito dal
database updatecomando . - Crea un database per il modello di dati specificato dalla classe di contesto del database.
Il parametro del nome della migrazione (InitialCreate nell'esempio) viene usato per il nome file. Il nome della migrazione può essere qualsiasi nome di file valido. È consigliabile scegliere una parola o una frase che riepiloga le operazioni eseguite nella migrazione. Ad esempio, una migrazione che ha aggiunto una tabella di reparto potrebbe essere denominata "AddDepartmentTable".
Tabella della cronologia delle migrazioni
- Usare lo strumento SSOX o SQLite per esaminare il database.
- Si noti l'aggiunta di una
__EFMigrationsHistorytabella. La__EFMigrationsHistorytabella tiene traccia delle migrazioni applicate al database. - Visualizzare i dati nella
__EFMigrationsHistorytabella. Mostra una riga per la prima migrazione.
Istantanea del modello di dati
Le migrazioni creano uno snapshot del modello di dati corrente in Migrations/SchoolContextModelSnapshot.cs. Quando si aggiunge una migrazione, Entity Framework determina le modifiche apportate confrontando il modello di dati corrente con il file di snapshot.
Poiché il file di snapshot tiene traccia dello stato del modello di dati, non è possibile eliminare una migrazione eliminando il <timestamp>_<migrationname>.cs file. Per eseguire il backup della migrazione più recente, usare il migrations remove comando .
migrations remove elimina la migrazione e garantisce che lo snapshot venga reimpostato correttamente. Per ulteriori informazioni, vedere dotnet ef migrations remove.
Vedere Reimpostazione di tutte le migrazioni per rimuovere tutte le migrazioni.
Applicazione delle migrazioni nell'ambiente di produzione
È consigliabile che le app di produzione nonchiamino Database.Migrate all'avvio dell'applicazione.
Migrate non deve essere chiamato da un'app distribuita in una server farm. Se l'app viene ridimensionata in più istanze del server, è difficile assicurarsi che gli aggiornamenti dello schema del database non vengano eseguiti da più server o in conflitto con l'accesso in lettura/scrittura.
La migrazione del database deve essere eseguita come parte della distribuzione e in modo controllato. Gli approcci alla migrazione del database di produzione includono:
- Uso delle migrazioni per creare script SQL e usare gli script SQL nella distribuzione.
- Esecuzione di
dotnet ef database updatein un ambiente controllato.
Risoluzione dei problemi
Se l'app usa SQL Server LocalDB e visualizza l'eccezione seguente:
SqlException: Cannot open database "ContosoUniversity" requested by the login.
The login failed.
Login failed for user 'user name'.
La soluzione potrebbe essere quella di eseguire dotnet ef database update nel prompt dei comandi.
Risorse aggiuntive
- EF Core Interfaccia della riga di comando.
- Comandi dell'interfaccia della riga di comando dotnet ef migrations
- Console di Gestione pacchetti (Visual Studio)
Passaggi successivi
L'esercitazione successiva sviluppa il modello di dati, aggiungendo proprietà di entità e nuove entità.
In questa esercitazione viene usata la EF Core funzionalità delle migrazioni per la gestione delle modifiche del modello di dati.
Se si verificano problemi che non è possibile risolvere, scaricare l'app completata.
Quando viene sviluppata una nuova app, il modello di dati cambia frequentemente. Ogni volta che il modello cambia, il modello non viene sincronizzato con il database. Questa esercitazione è iniziata configurando l'Entity Framework per creare il database se questo non esiste. Ogni volta che il modello di dati cambia:
- Il database viene eliminato.
- Ef crea un nuovo oggetto che corrisponde al modello.
- L'app esegue il seeding del database con i dati di test.
Questo approccio per mantenere il database sincronizzato con il modello di dati funziona correttamente fino a quando l'app non deve essere distribuita nell'ambiente di produzione. Quando l'app è in esecuzione nell'ambiente di produzione, in genere archivia i dati che devono essere mantenuti. L'app non può iniziare con un database di test ogni volta che viene apportata una modifica, ad esempio l'aggiunta di una nuova colonna. La EF Core funzionalità Migrazioni risolve questo problema consentendo di EF Core aggiornare lo schema del database invece di creare un nuovo database.
Anziché eliminare e ricreare il database quando il modello di dati cambia, le migrazioni aggiornano lo schema e conservano i dati esistenti.
Eliminare il database
Usare Esplora oggetti di SQL Server (SSOX) o il database drop comando :
Nella console di Gestione pacchetti eseguire il comando seguente:
Drop-Database
Eseguire Get-Help about_EntityFrameworkCore dal PMC per ottenere informazioni della guida.
Creare una migrazione iniziale e aggiornare il database
Compilare il progetto e creare la prima migrazione.
Add-Migration InitialCreate
Update-Database
Esaminare i metodi di salita e discesa
Codice EF Coremigrations add generato dal comando per creare il database. Questo codice di migrazione si trova nel Migrations\<timestamp>_InitialCreate.cs file . Il Up metodo della InitialCreate classe crea le tabelle di database che corrispondono ai set di entità del modello di dati. Il Down metodo li elimina, come illustrato nell'esempio seguente:
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true),
Credits = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});
migrationBuilder.CreateTable(
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Enrollment");
migrationBuilder.DropTable(
name: "Course");
migrationBuilder.DropTable(
name: "Student");
}
}
Le migrazioni invocano il metodo Up per implementare le modifiche al modello dei dati durante una migrazione. Quando viene immesso un comando per eseguire il rollback dell'aggiornamento, le migrazioni chiamano il Down metodo .
Il codice precedente è relativo alla migrazione iniziale. Questo codice è stato creato quando è stato eseguito il migrations add InitialCreate comando. Il parametro del nome della migrazione ("InitialCreate" nell'esempio) viene usato per il nome del file. Il nome della migrazione può essere qualsiasi nome di file valido. È consigliabile scegliere una parola o una frase che riepiloga le operazioni eseguite nella migrazione. Ad esempio, una migrazione che ha aggiunto una tabella di reparto potrebbe essere denominata "AddDepartmentTable".
Se viene creata la migrazione iniziale e il database esiste:
- Viene generato il codice di creazione del database.
- Il codice di creazione del database non deve essere eseguito perché il database corrisponde già al modello di dati. Se viene eseguito il codice di creazione del database, non apporta modifiche perché il database corrisponde già al modello di dati.
Quando l'app viene distribuita in un nuovo ambiente, è necessario eseguire il codice di creazione del database per creare il database.
In precedenza il database è stato eliminato e non esiste, quindi le migrazioni creano il nuovo database.
Istantanea del modello di dati
Le migrazioni creano uno snapshot dello schema del database corrente in Migrations/SchoolContextModelSnapshot.cs. Quando si aggiunge una migrazione, Entity Framework determina le modifiche apportate confrontando il modello di dati con il file di snapshot.
Per eliminare una migrazione, usare il comando seguente:
Rimuovi-Migrazione
Il comando remove migrations elimina la migrazione e garantisce che lo snapshot venga reimpostato correttamente.
Rimuovere EnsureCreated e testare l'app
Per lo sviluppo iniziale, EnsureCreated è stato usato. In questa esercitazione vengono usate le migrazioni.
EnsureCreated presenta le limitazioni seguenti:
- Ignora le migrazioni e crea il database e lo schema.
- Non crea una tabella delle migrazioni.
- Non può essere usato con le migrazioni.
- È progettato per il test o la creazione rapida di prototipi in cui il database viene eliminato e ricreato di frequente.
Rimuovi EnsureCreated:
context.Database.EnsureCreated();
Eseguire l'app e verificare che il database sia sottoposto a seeding.
Esaminare il database
Usare Esplora oggetti di SQL Server per esaminare il database. Si noti l'aggiunta di una __EFMigrationsHistory tabella. La __EFMigrationsHistory tabella tiene traccia delle migrazioni applicate al database. Visualizzare i dati nella __EFMigrationsHistory tabella, che mostra una riga per la prima migrazione. L'ultimo log nell'esempio di output del CLI precedente mostra l'istruzione SQL INSERT che crea questa riga.
Eseguire l'app e verificare che tutto funzioni.
Applicazione delle migrazioni nell'ambiente di produzione
È consigliabile che le app di produzione nonchiamino Database.Migrate all'avvio dell'applicazione.
Migrate non deve essere chiamato da un'app nella server farm. Ad esempio, se l'app è stata distribuita nel cloud con scalabilità orizzontale (sono in esecuzione più istanze dell'app).
La migrazione del database deve essere eseguita come parte della distribuzione e in modo controllato. Gli approcci alla migrazione del database di produzione includono:
- Uso delle migrazioni per creare script SQL e usare gli script SQL nella distribuzione.
- Esecuzione di
dotnet ef database updatein un ambiente controllato.
EF Core usa la __MigrationsHistory tabella per verificare se è necessario eseguire migrazioni. Se il database è up-to-date, non viene eseguita alcuna migrazione.
Risoluzione dei problemi
Scaricare l'app completata.
L'app genera l'eccezione seguente:
SqlException: Cannot open database "ContosoUniversity" requested by the login.
The login failed.
Login failed for user 'user name'.
Soluzione: Eseguire dotnet ef database update