using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using CredentialManager.Data; namespace CredentialManager.Services; /// /// Interfaccia per l'inizializzazione del database /// public interface IDatabaseInitializer { Task InitializeAsync(); Task DatabaseExistsAsync(); } /// /// Servizio per l'inizializzazione del database SQLite /// public class DatabaseInitializer : IDatabaseInitializer { private readonly CredentialDbContext _context; private readonly ILogger _logger; public DatabaseInitializer(CredentialDbContext context, ILogger logger) { _context = context; _logger = logger; } public async Task InitializeAsync() { try { _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(); if (created) { _logger.LogInformation("Database creato con successo"); // Aggiungi dati di esempio se necessario await SeedInitialDataAsync(); } else { _logger.LogInformation("Database esistente trovato"); // Verifica che le tabelle esistano await VerifyTablesAsync(); // Applica migrazioni se necessario await ApplyMigrationsAsync(); } } catch (Exception ex) { _logger.LogError(ex, "Errore durante l'inizializzazione del database"); throw; } } private async Task VerifyTablesAsync() { try { // Prova a fare una query semplice per verificare che la tabella esista await _context.Credentials.CountAsync(); _logger.LogInformation("Verifica tabelle completata con successo"); } catch (Exception ex) { _logger.LogWarning("Tabelle mancanti, ricreazione database..."); // Se le tabelle non esistono, le ricreiamo await _context.Database.EnsureDeletedAsync(); await _context.Database.EnsureCreatedAsync(); await SeedInitialDataAsync(); _logger.LogInformation("Database ricreato con successo"); } } public async Task 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 { 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 ApplyMigrationsAsync() { try { _logger.LogInformation("Verifica e applicazione migrazioni..."); // Verifica se la colonna RestServiceType esiste usando una query diretta 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"); } } catch (Exception ex) { _logger.LogError(ex, "Errore nell'applicazione delle migrazioni"); throw; } } }