From d837339f7e7656750130325c6d59c98f5705b731 Mon Sep 17 00:00:00 2001 From: Alessio Dal Santo Date: Wed, 2 Jul 2025 16:32:31 +0200 Subject: [PATCH] Corregge il problema di inizializzazione database per la tabella DataCouplerProfiles - Sostituito EnsureCreatedAsync con MigrateAsync nel DatabaseInitializer - Aggiunta gestione automatica delle migrazioni pendenti al startup - Migliorata verifica delle tabelle includendo DataCouplerProfiles - Rimossa logica obsoleta di ApplyMigrationsAsync - Risolto errore "no such table: DataCouplerProfiles" nel salvataggio profili Questo fix garantisce che tutte le migrazioni vengano applicate correttamente, permettendo il corretto funzionamento del sistema di salvataggio --- .../Services/DatabaseInitializer.cs | 168 +++++------------- Data_Coupler/wwwroot/data/credentials.db | Bin 86016 -> 126976 bytes Data_Coupler/wwwroot/data/credentials.db-shm | Bin 32768 -> 32768 bytes Data_Coupler/wwwroot/data/credentials.db-wal | Bin 0 -> 49472 bytes 4 files changed, 44 insertions(+), 124 deletions(-) diff --git a/CredentialManager/Services/DatabaseInitializer.cs b/CredentialManager/Services/DatabaseInitializer.cs index 9893749..30e0de5 100644 --- a/CredentialManager/Services/DatabaseInitializer.cs +++ b/CredentialManager/Services/DatabaseInitializer.cs @@ -31,13 +31,17 @@ public class DatabaseInitializer : IDatabaseInitializer { _logger.LogInformation("Inizializzazione database in corso..."); - // Per SQLite con EnsureCreatedAsync è più semplice e sicuro - // Crea il database e le tabelle se non esistono - var created = await _context.Database.EnsureCreatedAsync(); + // Verifica se il database esiste + var databaseExists = await _context.Database.CanConnectAsync(); - if (created) + if (!databaseExists) { - _logger.LogInformation("Database creato con successo"); + _logger.LogInformation("Database non esistente, creazione in corso..."); + + // Applica tutte le migrazioni per creare il database con la struttura più recente + await _context.Database.MigrateAsync(); + + _logger.LogInformation("Database creato con tutte le migrazioni applicate"); // Aggiungi dati di esempio se necessario await SeedInitialDataAsync(); @@ -46,11 +50,23 @@ public class DatabaseInitializer : IDatabaseInitializer { _logger.LogInformation("Database esistente trovato"); + // Applica eventuali migrazioni pendenti + var pendingMigrations = await _context.Database.GetPendingMigrationsAsync(); + if (pendingMigrations.Any()) + { + _logger.LogInformation("Trovate {Count} migrazioni pendenti: {Migrations}", + pendingMigrations.Count(), string.Join(", ", pendingMigrations)); + + await _context.Database.MigrateAsync(); + _logger.LogInformation("Migrazioni applicate con successo"); + } + else + { + _logger.LogInformation("Nessuna migrazione pendente"); + } + // Verifica che le tabelle esistano await VerifyTablesAsync(); - - // Applica migrazioni se necessario - await ApplyMigrationsAsync(); } } catch (Exception ex) @@ -68,28 +84,35 @@ public class DatabaseInitializer : IDatabaseInitializer await _context.Credentials.CountAsync(); _logger.LogInformation("Tabella Credentials verificata con successo"); - // Verifica se la tabella KeyAssociations esiste, se non esiste la crea senza ricreare tutto il database + // Verifica se la tabella KeyAssociations esiste try { await _context.KeyAssociations.CountAsync(); _logger.LogInformation("Tabella KeyAssociations verificata con successo"); } - catch (Exception) + catch (Exception ex) { - _logger.LogInformation("Tabella KeyAssociations non trovata, creazione tramite migrazione..."); - await CreateKeyAssociationsTableAsync(); + _logger.LogWarning(ex, "Tabella KeyAssociations non accessibile"); + } + + // Verifica se la tabella DataCouplerProfiles esiste + try + { + await _context.DataCouplerProfiles.CountAsync(); + _logger.LogInformation("Tabella DataCouplerProfiles verificata con successo"); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Tabella DataCouplerProfiles non accessibile"); } } - catch (Exception) + catch (Exception ex) { - _logger.LogWarning("Tabella Credentials mancante, ricreazione database..."); + _logger.LogError(ex, "Errore nella verifica delle tabelle"); - // Solo se la tabella principale non esiste, ricreiamo tutto - await _context.Database.EnsureDeletedAsync(); - await _context.Database.EnsureCreatedAsync(); - await SeedInitialDataAsync(); - - _logger.LogInformation("Database ricreato con successo"); + // Se ci sono problemi gravi, prova a riapplicare le migrazioni + _logger.LogInformation("Tentativo di riapplicazione delle migrazioni..."); + await _context.Database.MigrateAsync(); } } @@ -148,110 +171,7 @@ public class DatabaseInitializer : IDatabaseInitializer _logger.LogError(ex, "Errore durante il seeding dei dati iniziali"); throw; } - } private async Task ApplyMigrationsAsync() - { - try - { - _logger.LogInformation("Verifica e applicazione migrazioni..."); - - // Migrazione 1: Verifica se la colonna RestServiceType esiste - try - { - await _context.Database.ExecuteSqlRawAsync( - "SELECT RestServiceType FROM Credentials LIMIT 1"); - _logger.LogInformation("Colonna RestServiceType già presente"); - } - catch (Microsoft.Data.Sqlite.SqliteException) - { - // La colonna non esiste, la aggiungiamo - _logger.LogInformation("Aggiunta colonna RestServiceType..."); - await _context.Database.ExecuteSqlRawAsync( - "ALTER TABLE Credentials ADD COLUMN RestServiceType TEXT"); - _logger.LogInformation("Colonna RestServiceType aggiunta con successo"); - } - - // Migrazione 2: Elimina vecchia tabella RecordAssociations se esiste e crea KeyAssociations - try - { - // Prova a eliminare la vecchia tabella se esiste - await _context.Database.ExecuteSqlRawAsync("DROP TABLE IF EXISTS RecordAssociations"); - _logger.LogInformation("Vecchia tabella RecordAssociations eliminata"); - } - catch (Exception) - { - // Ignora errori se la tabella non esiste - } - - // Verifica se la tabella KeyAssociations esiste - try - { - await _context.Database.ExecuteSqlRawAsync( - "SELECT COUNT(*) FROM KeyAssociations LIMIT 1"); - _logger.LogInformation("Tabella KeyAssociations già presente"); - } - catch (Microsoft.Data.Sqlite.SqliteException) - { - // La tabella non esiste, la creiamo - _logger.LogInformation("Creazione tabella KeyAssociations..."); - - // Crea la tabella - await _context.Database.ExecuteSqlRawAsync(@" - CREATE TABLE KeyAssociations ( - Id INTEGER PRIMARY KEY AUTOINCREMENT, - KeyValue TEXT NOT NULL, - SourceKeyField TEXT NOT NULL, - DestinationKeyField TEXT NOT NULL, - DestinationEntity TEXT NOT NULL, - DestinationId TEXT NOT NULL, - RestCredentialName TEXT NOT NULL, - CreatedAt TEXT NOT NULL DEFAULT (datetime('now')), - UpdatedAt TEXT, - LastVerifiedAt TEXT, - IsActive INTEGER NOT NULL DEFAULT 1, - SourcesInfo TEXT, - AdditionalInfo TEXT - )"); - - // Crea gli indici - await _context.Database.ExecuteSqlRawAsync(@" - CREATE INDEX IX_KeyAssociations_KeyValue - ON KeyAssociations (KeyValue)"); - - await _context.Database.ExecuteSqlRawAsync(@" - CREATE UNIQUE INDEX IX_KeyAssociations_Unique - ON KeyAssociations (KeyValue, DestinationEntity, RestCredentialName)"); - - await _context.Database.ExecuteSqlRawAsync(@" - CREATE INDEX IX_KeyAssociations_DestinationEntity - ON KeyAssociations (DestinationEntity)"); - - await _context.Database.ExecuteSqlRawAsync(@" - CREATE INDEX IX_KeyAssociations_RestCredentialName - ON KeyAssociations (RestCredentialName)"); - - await _context.Database.ExecuteSqlRawAsync(@" - CREATE INDEX IX_KeyAssociations_IsActive - ON KeyAssociations (IsActive)"); - - await _context.Database.ExecuteSqlRawAsync(@" - CREATE INDEX IX_KeyAssociations_CreatedAt - ON KeyAssociations (CreatedAt)"); - - await _context.Database.ExecuteSqlRawAsync(@" - CREATE INDEX IX_KeyAssociations_LastVerifiedAt - ON KeyAssociations (LastVerifiedAt)"); - - _logger.LogInformation("Tabella KeyAssociations creata con successo"); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Errore nell'applicazione delle migrazioni"); - throw; - } - } - - private async Task CreateKeyAssociationsTableAsync() + } private async Task CreateKeyAssociationsTableAsync() { try { diff --git a/Data_Coupler/wwwroot/data/credentials.db b/Data_Coupler/wwwroot/data/credentials.db index aae6556c041e715de8db81b87dcfba774d99067b..98fd88895d447ef56488391f1c6e88df53180f5f 100644 GIT binary patch delta 2567 zcmchZPi)(C6vyqPv6Hl}n~l~4L^Ji;X3AI`B%ak=uyTnzy1F}qFm_?eT zi8ld4axH{F?66gqwrj6kIM4&qPQ7qI(Kz9uj2W|6QUCbp)nml2zg#orq@K^r?Kbs`}3Fi7>FhoV+)J%tFy_4 zWHOnEe!%mKJWnAj4}A}#AJg}cuSU;Z_INj$7$3XB&-2k3A5X-SVyaTfNUD^s-)U6k z=6bXKiBgqY3$y&}Rpas84Znweh|!1iLlohA`XcAu#0LuC`TB6_(cu!lOqdwh*w4f= z{tr!3bOH+y`+J|g<2g#`xtY-4)O#WP6-GazM@P4*7nC&e>&UyqJ0wlq^&R;9Lrw1= zUg+7wUm=DkxTZ%YNoFmM>mMq$iu`$QOLR#|~(riMpV215(#d3NyLNX$P`{;DIbW^U#HC2(SIkz*Ic8ApLC)G*R8p}%C z1J-8F>7!wiNh9cZKj?zAZE6`hSu1ZFPl>SRqOxdu^o2Px;PePHz=7tamb%fBD=F1w zt8<#WSSPgV#^{S>G2`^J6C|^Ow7Jqxo1E54l~v`gTd_?IgqG_B=nMA7h|_1rN#+*9 zy4l9k+;2ffZmCL5Qk8nG$5ogdi0(ujC#2SC9OivEY0T-%Z;_0GV0ZdyXmPWar^{(a zoXncDhlxD`I^o^ftq|y9Pn;#0Rg}YmYYtkwZ;HrCQhO9>*oo~z{U$B7Pq~3NK7}J3f z#B$C6fnf4<7E94sfQ(Qe66_M7*D0>js4F$qxgncX6hIYMk6_x`n0kJd?%K)(~5X%8E$VnhIG8-GE-5HrT zHvVN|WC4?`V3KWPqb4IGDz^o@1e@vP+ni9o2#n7F1^lkq diff --git a/Data_Coupler/wwwroot/data/credentials.db-wal b/Data_Coupler/wwwroot/data/credentials.db-wal index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8e955bda66c739439a5f59c6cd94cd1c39da3588 100644 GIT binary patch literal 49472 zcmeI*PiP$19S87HHjP;)@)~THDvDxdN=T_!!+URLcK#e3k7sQHu|-ze3gXxevpY}9 zCZid7X7;dgMOmK`3Wgq98XpTSbtx?^^kC>EPz>oMw?a>;)AkaAdutP#L*MLbBt^R` zjmg0gdWOL5SgO1)RsLQ1oA`ze0uX=z1Rwwb2tWV=5P$##AOL}{qrf*y zCAD1lQqPUL8v&1BiKEp{z>|}YmCii&GVeJ_616*C+KIwM`g3Kf^zA7(<~|S8ju#}4 zi%6%kSowOv<(0MfKX-oe^K4yUs#2CJbpwSsJGImz2y#=#*6wS+NdjHYCI!IWIy?DPJ)y+PH2LEkw4YQv$Ef-+07 zsA?JdXwdC0?ckt;TA~wc%;{v>Lj`?tZ&0QZR^++aHq`wtTT5Y zsgq)gOr;Yq3}(u+H_yyCQaKePX2JvBPPxA`V)?BoZ)|!kF&h_ETjTC)H{@h6vR&-( zz!yVXHa;(U>s$5`MctKZ;o?$l#s&YCQpQCtvu>WD}=C$QslJfPTsj)!VJk@NK*t({ux~0_&@tP*? zCD>UPc>cM+RBqq>{L`bNZL0FIB)+gg00Izz00bZa0SG_<0uX=z1R!u|1?EaldEa$` znJijFIE|F7Sm^`Qp$9$ALot0uX=z1Rwwb2tWV=5P$##Ah3@>sU(#} z_tRNPzAo^a+YkQwQNV5u*9AV4DxdAM19U+E0uX=z1Rwwb2tWV=5P$##AaE!Jj+9Q7 zvrj*WgP+X;{zp9-7>DeoP$Nd6_^0eZhApijgKmY;|fB*y_009U<00M;tN~Lmk zzrZuu1M+o&`uFbqmL2)vZLA9vW<((bAOHafKmY;|fB*y_009U<;7|%|eU4x*JNSHE z;D2xZ@%|5vekaA}2oB{b#X&;=0uX=z1Rwwb2tWV=5P$##3JGMNBgp>Of+&7AdqBP} z@UzD6e*ED_y?eM{pb#U9AOHafKmY;|fB*y_009U<00M_rVC#N?(;~p>d|kl#@Y;XW z?=HSOTo?F6s(f;28vZcWvTzVt1(81>&3ns`Me&rFNA5_bK32w8>WQNwM!)1-1_zC zrH0d7zBu0$ca9GKmvwD{S@YDiHD)ua5KU}mZE}}&LvF@in5^=+?xkF|<(=B*uH8^- zY5EnpDlhSN6#I+a^%jq1+pNl$y^W1dxaMZZCfl?s@4Pn^d-J{2Yk7$XY3&KQLI)WR z4jI>I!>LaUSyQMRKkipH`|7~-(_nl%rbRm(2+AL4u06B77EHN zU9%V+b4JyN3VL=-&_aXIn}N7=CqF+;MO?O;RWn9|=3PYwAyLaLqBC_&P*%NJnK~)v z!Bjf&!eBZ)d-KeU;|^}9ADuG$ttfA7daZzGf4+ZfaDDBDoD8Pc7dt%g#rTyC!i(NI z7bBl9$~vK!cA_xv&3nWkm(9gRy{PLXFY}&kuX;hkv!9mu^=>ETVsBebK40~^LAv4v zUGb2x8w6E39Sp)zygu0fuyym=axY2w`Vh`oAZ(s$wn}VWQ&ip3a?Eet};e|Hsni@8A2y@P2{&Qsw?5ebvJ+hX4d1009U<00Izz00bZa0SG|g Rs|Y+>a?5*G40f*z{2#r7K_~zK literal 0 HcmV?d00001