Esempio di una migrazione
In questo esempio si esaminerà una migrazione con il compito di modificare il tipo delle colonne "wk_start","wk_finish","wk_close" da stringa a datetime nella tabella "mes_workings".
Step 1: Modifica del modello
Cerco in .\industry-pronet_iot\DatabaseModels\Repository\Models il file con il modello della tabella "mes_workings" e vado a sostituire:
/// <summary>
/// Date e ora inizio lotto
/// </summary>
public string? WkStart { get; set; }
/// <summary>
/// Data e ora ultimo parziale
/// </summary>
public string? WkFinish { get; set; }
/// <summary>
/// Data e ora chiusura lotto
/// </summary>
public string? WkClose { get; set; }
con:
/// <summary>
/// Date e ora inizio lotto
/// </summary>
public DateTime? WkStart { get; set; }
/// <summary>
/// Data e ora ultimo parziale
/// </summary>
public DateTime? WkFinish { get; set; }
/// <summary>
/// Data e ora chiusura lotto
/// </summary>
public DateTime? WkClose { get; set; }
Step 2: Inizializzo la migrazione
Visto che stiamo andando a modificare il tipo della colonna chiameremo la migrazione "FixMesWorkingsTimeTipe" così da far capire solo dal nome quali saranno i cambiamenti.
Per farlo uso il comando dotnet ef migration add FixMesWorkingsTimeTipe che mi genererà un file con lo stesso nome in .\industry-pronet_iot\DatabaseModels\Migrations.
Step 3: Personalizzare la migrazione
EF genera in modo automatico una migrazione basandosi sui cambiamenti al modello; tuttavia nel nostro caso abbiamo bisogno di qualcosa di più specifico, andiamo quindi a pulire tutto finchè non abbiamo un "template" su cui lavorare.
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProRob.DatabaseModels.Migrations
{
/// <inheritdoc />
public partial class FixMesWorkingsTimeType : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}
La funzione void Up(MigrationBuilder migrationBuilder) indica i passaggi che vanno eseguiti per effettuare il passaggio ad una certa migrazione, void Down(MigrationBuilder migrationBuilder) i passaggi per tornare indietro da una certa migrazione.
Nel nostro caso dovremmo:
- Creare una colonna temporanea
- Convertire le stringe in datetime e inserirle in questa colonna
- Eliminare la vecchia colonna
- Rinomirare così da mantenere una certa consistenza nel database
Ecco come fare:
-
migrationBuilder.AddColumn<DateTime>(
name: "wk_start_new",
table: "mes_workings",
type: "timestamp",
maxLength: 32,
nullable: true,
comment: "Data e ora chiusura lotto"); -
migrationBuilder.Sql(@"
UPDATE mes_workings
SET wk_start_new =
CASE
WHEN wk_start LIKE '%-%' THEN STR_TO_DATE(wk_start, '%Y-%m-%d %H:%i:%s')
WHEN wk_start LIKE '%/%' THEN STR_TO_DATE(wk_start, '%m/%d/%Y %H:%i:%s')
ELSE NULL
END"); -
migrationBuilder.DropColumn(
name: "wk_start",
table: "mes_workings"); -
migrationBuilder.RenameColumn(
name: "wk_start_new",
table: "mes_workings",
newName: "wk_start");
Per il roll-back della migrazione le istruzioni saranno ovviamente leggermente diverse:
migrationBuilder.AddColumn<String>(
name: "wk_start_new",
table: "mes_workings",
maxLength: 32,
nullable: true,
comment: "Data e ora inizio lotto");
migrationBuilder.Sql(
@"UPDATE mes_workings
SET wk_start_new = DATE_FORMAT(wk_start,'%Y-%m-%d %H:%i:%s')");
migrationBuilder.DropColumn(
name: "wk_start",
table: "mes_workings");
migrationBuilder.RenameColumn(
name: "wk_start_new",
table: "mes_workings",
newName: "wk_start"
);
Chiaramente questi passaggi andranno eseguiti per ognuna delle tre colonne da modificare.
Step 4: Applico la migrazione
Basta lanciare da console: dotnet ef database update.