Passa al contenuto principale

Allineamento di un DB

Entity framework si occupa autonomamente di gestire i passaggi necessari all'allineamente di un DB con le sue migrazioni; in caso quindi un database abbia già la firma (la tabella __efmigrationhistory è popolata) basterà utilizzare i comandi di migrazione di EF per eseguire l'allineamento.
Se il database non è firmato o se non è disponibile (nel caso di un nuovo cliente) invece sarà necessario prima eseguire qualche processo preliminare per poter aggiornare il modello in maniera automatica.

Questo viene considerato il primo passaggio perchè il resto delle operazioni suppone che il database collegato al modello abbia la firma di EF

Creare un databse con la struttura di Entity framework

Con EF

Sempre puntando ad un database vuoto (manager_settings.json) posso lanciare dotnet ef database update da Visual Studio per creare automaticamente la struttura del modello nel DB

Firmare un database con Entity Framework

Creare un database con la struttura di base

La pratica corretta per firmare un database è quella di allineare la sua struttura con la struttuna iniziale del modello Entity Framework, con struttura iniziale si intende il modello nella sua prima migrazione.
Abbiamo bisogno di avere questa struttura da qualche parte.
In caso non sia già disponibile è possibile creare uno schema velocemente con entity framework con:

dotnet ef database update initial

Calcolare le differenze con il database attuale

Verranno ora calcolate le differenze tra la struttura firma e la struttura del DB corrente, per ottenere ciò verrà utilizzato il tool "atlas.exe" che richiederà il database che vogliamo allineare e la struttura di quello già firmato da EF con la seguente sintassi:

from: Il database corrente, quello che vogliamo firmare ed aggiornare.
to: Il database a cui vogliamo allinearci (Solitamente la struttura ef appena creata).

.\utility\atlas.exe schema diff --from mysql://user:pass@host:port/db  
--to mysql://user:pass@host:port/db > differences.sql

Viene riportato di sotto un esempio pratico:

C:\PROROB\utility>atlas.exe schema diff --from mysql://root:XXXX-XXXX-XXXX-XXXX@192.168.161.26:3306/pronet-iot_ef --to mysql://root:XXXX-XXXX-XXXX-XXXX@192.168.161.26:3306/pronet-iot_database-model > differences.sql

Al momento il file differences.sql ha qualche imperfezione e non può essere utilizzato.

  1. Eliminare il controllo per utf8mb3 che potrebbe essere presente nella prima riga.

  2. Disattivare il controllo delle chiavi esterne, aggiungendo questa riga all' inizio dello script.

    SET FOREIGN_KEY_CHECKS=0;
  3. Disabilitare (e poi riattivare) gli update di timestamp automatico di alcune colonne per preservare il dato. Queste query andrebbero eseguite rispettivamente prima e dopo lo script generato con Atlas.

    -- DECTIVATE
    ALTER TABLE mes_workings
    CHANGE wk_timestamp
    wk_timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP

    ALTER TABLE mes_workorders
    CHANGE wo_timestamp
    wo_timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP

    ALTER TABLE scada_subworkings
    CHANGE sk_timestamp
    sk_timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP


    -- ACTIVATE ANGAIN BACK
    ALTER TABLE mes_workings
    CHANGE wk_timestamp
    wk_timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

    ALTER TABLE mes_workorders
    CHANGE wo_timestamp
    wo_timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

    ALTER TABLE scada_subworkings
    CHANGE sk_timestamp
    sk_timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  4. Riparare eventuali dati mancanti e/o errati che vengono segnalati come errore, di seguito sono riportate query di fix per eventuali date mancanti in mes_workorder (problema spesso riscontrato)

    -- DATE
    UPDATE mes_workorders
    SET wo_delivery_date = COALESCE(wo_delivery_date, wo_timestamp)
    WHERE wo_delivery_date IS NULL;

    UPDATE mes_workorders
    SET wo_nominal_delivery_date = COALESCE(wo_nominal_delivery_date, wo_delivery_date)
    WHERE wo_nominal_delivery_date IS NULL;

    UPDATE mes_workorders
    SET wo_nominal_scheduling_date = COALESCE(wo_nominal_scheduling_date, wo_scheduling_date)
    WHERE wo_nominal_scheduling_date IS NULL;

File sql di template

SQL TEMPLATE

Lanciare lo script di allineamento

Dopo aver eseguito le modifiche allo scritp è possibile applicare il file .sql al nostro df che dobbiamo allineare, per lo scopo verrà utilizzato:

C:\PROROB\bin_srv\mariadb\bin\mysql -h <host> -u <user> -p<password> <db> < <differences file>

-h <host> non sarà ovviamente necessario in caso facessimo questa operazione in locale.

Riempire la tabella delle migrazioni

Come ultima operazione avremo quella di copiare il contenuto della tabella __efmigrationhistory visto che non è presente un comando che lo faccia in automatico nelle differenze; possiamo utilizzare la seguente query per lo scopo

INSERT INTO `__efmigrationshistory`(`migration_id`, `product_version`) VALUES ('20231016094430_Initial','7.0.12')

Aggiornare il database

A questo il nostro database sarà allineato alla prima migrazione del nostro modello EF, sarà quindi necessario portarlo all'ultima migrazione. Possiamo usare pronet per questo se nella macchiana del cliente abbiamo una versione aggiornata.

ProNet.exe --migrate-database

Creazione script idempotenti

dotnet ef migrations script --idempotent

Lo script idempotente è l'insieme di istruzioni necessarie per allineare un certo DB, si può vedere un po' come quello che automaticamente viene eseguito normalmente quando viene lanciato dotnet ef database update.