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;
}
}
}