d837339f7e
- 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
239 lines
8.3 KiB
C#
239 lines
8.3 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging;
|
|
using CredentialManager.Data;
|
|
|
|
namespace CredentialManager.Services;
|
|
|
|
/// <summary>
|
|
/// Interfaccia per l'inizializzazione del database
|
|
/// </summary>
|
|
public interface IDatabaseInitializer
|
|
{
|
|
Task InitializeAsync();
|
|
Task<bool> DatabaseExistsAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Servizio per l'inizializzazione del database SQLite
|
|
/// </summary>
|
|
public class DatabaseInitializer : IDatabaseInitializer
|
|
{
|
|
private readonly CredentialDbContext _context;
|
|
private readonly ILogger<DatabaseInitializer> _logger;
|
|
|
|
public DatabaseInitializer(CredentialDbContext context, ILogger<DatabaseInitializer> logger)
|
|
{
|
|
_context = context;
|
|
_logger = logger;
|
|
} public async Task InitializeAsync()
|
|
{
|
|
try
|
|
{
|
|
_logger.LogInformation("Inizializzazione database in corso...");
|
|
|
|
// Verifica se il database esiste
|
|
var databaseExists = await _context.Database.CanConnectAsync();
|
|
|
|
if (!databaseExists)
|
|
{
|
|
_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();
|
|
}
|
|
else
|
|
{
|
|
_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();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Errore durante l'inizializzazione del database");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private async Task VerifyTablesAsync()
|
|
{
|
|
try
|
|
{
|
|
// Verifica che la tabella principale Credentials esista
|
|
await _context.Credentials.CountAsync();
|
|
_logger.LogInformation("Tabella Credentials verificata con successo");
|
|
|
|
// Verifica se la tabella KeyAssociations esiste
|
|
try
|
|
{
|
|
await _context.KeyAssociations.CountAsync();
|
|
_logger.LogInformation("Tabella KeyAssociations verificata con successo");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_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 ex)
|
|
{
|
|
_logger.LogError(ex, "Errore nella verifica delle tabelle");
|
|
|
|
// Se ci sono problemi gravi, prova a riapplicare le migrazioni
|
|
_logger.LogInformation("Tentativo di riapplicazione delle migrazioni...");
|
|
await _context.Database.MigrateAsync();
|
|
}
|
|
}
|
|
|
|
public async Task<bool> DatabaseExistsAsync()
|
|
{
|
|
try
|
|
{
|
|
return await _context.Database.CanConnectAsync();
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private async Task SeedInitialDataAsync()
|
|
{
|
|
try
|
|
{
|
|
// Verifica se ci sono già dati
|
|
if (await _context.Credentials.AnyAsync())
|
|
{
|
|
_logger.LogInformation("Dati esistenti trovati. Seeding saltato.");
|
|
return;
|
|
}
|
|
|
|
_logger.LogInformation("Aggiunta dati di esempio...");
|
|
|
|
// Qui puoi aggiungere dati di esempio se necessario
|
|
// Ad esempio:
|
|
/*
|
|
var sampleCredentials = new List<CredentialEntity>
|
|
{
|
|
new CredentialEntity
|
|
{
|
|
Name = "Esempio Database",
|
|
Type = "Database",
|
|
Host = "localhost",
|
|
Port = 1433,
|
|
DatabaseName = "TestDB",
|
|
Username = "testuser",
|
|
CreatedAt = DateTime.UtcNow,
|
|
CreatedBy = "System",
|
|
IsActive = true
|
|
}
|
|
};
|
|
|
|
_context.Credentials.AddRange(sampleCredentials);
|
|
await _context.SaveChangesAsync();
|
|
*/
|
|
|
|
_logger.LogInformation("Dati di esempio aggiunti con successo");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Errore durante il seeding dei dati iniziali");
|
|
throw;
|
|
}
|
|
} private async Task CreateKeyAssociationsTableAsync()
|
|
{
|
|
try
|
|
{
|
|
_logger.LogInformation("Creazione tabella KeyAssociations...");
|
|
|
|
// Elimina la vecchia tabella se esiste
|
|
await _context.Database.ExecuteSqlRawAsync("DROP TABLE IF EXISTS RecordAssociations");
|
|
|
|
// Crea la nuova 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 nella creazione della tabella KeyAssociations");
|
|
throw;
|
|
}
|
|
}
|
|
}
|