Passa al contenuto principale

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:

  1. Creare una colonna temporanea
  2. Convertire le stringe in datetime e inserirle in questa colonna
  3. Eliminare la vecchia colonna
  4. Rinomirare così da mantenere una certa consistenza nel database

Ecco come fare:

  1.  migrationBuilder.AddColumn<DateTime>(
    name: "wk_start_new",
    table: "mes_workings",
    type: "timestamp",
    maxLength: 32,
    nullable: true,
    comment: "Data e ora chiusura lotto");
  2.  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");
  3.  migrationBuilder.DropColumn(
    name: "wk_start",
    table: "mes_workings");
  4.  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.