Passa al contenuto principale

AGGIORNARE MODELLO ENTITY FRAMEWORK

Migrazioni

Con il passaggio ad Entity Framework bisogna evitare nel modo più assoluto di apportare modifiche alla struttura del Database da MariaDB o PhpMyadmin. Tutti i cambiamenti vanno fatti nel modello localizzato in .\industry-pronet_iot\ProRob\DatabaseModels. Il Db verrà allineato in un secondo momento con i comandi appositi.

Le varie modifiche effettuate al modello vengono tenute traccia con le "migrazioni", questo passaggio sarà necessario per allineare i vari database.
Ogni volta che viene fatta una modifica al modello, quindi, è opportuno aggiungere una migrazione correlata. Il nome della migrazione può essere usato un po' come un messaggio di commit per spiegare i cambiamenti che sono stati effettuati.

Il nome della migrazione può essere usato un po' come un messaggio di commit, spiegherà quindi i vari cambiamenti che sono stati effettuati in quella migrazione.

Una volta modificato il modello posso usare questi comandi dalla console di Visual Studio in .\industry-pronet_iot\DatabaseModels per gestire le migrazioni:

Creare e applicare una migrazione

Per aggiungere una migrazione alla "firma" di Entity Framework:
dotnet ef migration add <migration_name>

Per eliminare l'ultima migrazione aggiunta:
dotnet ef migrations remove

Posso anche applicare i cambiamenti al database al momento in uso direttamente dalla console di Visual Studio con:
dotnet ef database update

Convenzione dei nomi per le migrazioni

Microsoft non specifica una convenzione per dare un nome alle migrazioni di EF, tuttavia, nella documentazione ufficiale usa come esempio:

dotnet ef migrations add AddBlogCreatedTimestamp

Si assume quindi che vada usato UpperCamelCase per chiamare le migrazioni (Anche se veniva usato qualcosa di differente prima)
Reference Microsoft

Personalizzare una migrazione

Quando viene aggiunta una migrazione viene creato automaticamente un file che ne descrive il comportamento.
Questi file sono localizzati in .\industry-pronet_iot\DatabaseModels\Migrations
alt text
E servono a regolare il comportamente del database quando ci si sposta da una migrazione ad un altra.
Viene lasciato di seguito un esempio di una migrazione che aggiunge al modello la colonna "st_insert_timestamp" alla tabella "scada_machine_status_history".

namespace ProRob.DatabaseModels.Migrations
{
/// <inheritdoc />
public partial class MachineStatusInsertTimestamp : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "st_insert_timestamp",
table: "scada_machine_status_history",
type:"timestamp",
nullable: false,
defaultValueSql: "current_timestamp()");
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "st_insert_timestamp",
table: "scada_machine_status_history");
}
}
}

Come si può notare migrationBuilder.Addcolumn<T>() si occupa di specificare il tipo, parametri di default, eventuali commenti, etc. etc.
Importante è modificare questo file secondo le esigenze PRIMA di applicare la migrazione al database con dotnet ef database update. In caso contrario si rischierebbe di allinearsi con dei dati parzialmente errati.

Gestione delle migrazioni

Essendo un operazione atomica ogni migrazione dovrebbe essere per quanto possibile slegata dalle altre, ognuna quindi dovrebbe andare ad modificare campi specifici e diversi del modello.
Migrazioni eseguite in modo ordinato ci permettono di evitare numerosi problemi nel caso branch diversi creano migrazioni diverse...queste saranno alla fine portate tutte nel merge e essendo eseguite in ordine possono essere applicate anche in maniera retroattiva.
Il codice che viene assegnato quindi ad ogni migrazione non preclude ad Entity framework di controllare se le precedenti siano state applicate al modello.

Merging delle migrazioni in main

Potrebbe succedere che vengano create contemporaneamente, e in branch diversi, diverse migrazioni (dovute a necessità differenti); per come EF le gestisce questo potrebbe essere un problema se non fatto con ordine e migrazioni successive potrebbero non vedere cambiamenti fatti in precedenza.
Al fine di evitare ogni problema se si creano una o più migrazioni prima di effettuare un merge in main:

  1. Portare il database locale o di test in cui si sta operando alla migrazione precedente a quelle inserite. alt text
    Usiamo come esempio le migrazioni nell'immagine; nel branch corrente sono state aggiunge AiaMode e MesWorkingDatetimeFix. Utilizzo quindi dotnet ef database update Indexes per tornare indietro

  2. Rimuovo tutte le migrazioni dopo il punto in cui ho portato il database, posso usare: dotnet ef migrations remove

  3. Eseguo il merge di main verso il mio branch (così da ottenere eventuali migrazioni mancanti), in caso sia necessario aggiornare il database di test

  4. Aggiungo ora una nuova migrazione, questa sarà l'unione di tutte quelle che ho tolto in precedenza

  5. IMPORTANTE controllo che la migrazione appena aggiunta apporti effettivamente dei cambiamenti (o i cambiamenti corretti) in quanto facendo riferimento al DbContexModelSnapshot i dati potrebbero avere discordanza. In caso si può aggiornare lo snapshop con i dati semplicemente rimuovendo la migrazione appena creata e ricreandola

  6. Se la migrazione aggiunta ha tutte le modifice necessarie al database posso portare le modifiche in main