feat: Corregge la logica di rilevamento database specificato nella connection string
- Modifica IsDatabaseSpecifiedInConnectionString per verificare prima il campo DatabaseName della credenziale - Aggiunge logging dettagliato per debugging del processo di connessione database - Corregge il flusso di connessione per evitare il modale quando il database è già specificato - Migliora la gestione degli errori nel caricamento tabelle dal database specificato - Rimuove codice non raggiungibile nella logica di connessione database Il bug precedente mostrava sempre il modale di selezione database anche quando il database era specificato nel campo DatabaseName della credenziale, ora la verifica segue la logica corretta: 1. Controlla se DatabaseName è valorizzato nella credenziale 2. Solo se vuoto, verifica i parametri Database=/Initial Catalog= nella connection string
This commit is contained in:
@@ -234,11 +234,11 @@
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else if (databaseTables.Any())
|
||||
else if (availableTableNames.Any())
|
||||
{
|
||||
<!-- Sezione Tabelle (modalità standard) -->
|
||||
<div class="mb-3">
|
||||
<h6>Tabelle Database (@databaseTables.Count disponibili):</h6>
|
||||
<h6>Tabelle Database (@availableTableNames.Count disponibili):</h6>
|
||||
|
||||
<!-- Campo di ricerca -->
|
||||
<div class="mb-2">
|
||||
@@ -1131,7 +1131,7 @@
|
||||
<div class="col-12">
|
||||
<ProfileSaver CanSave="CanSaveProfile()"
|
||||
SourceType="selectedSourceType"
|
||||
SourceSchema="@(databaseTables.Keys.FirstOrDefault()?.Split('.').FirstOrDefault())"
|
||||
SourceSchema="@(availableTableNames.FirstOrDefault()?.Split('.').FirstOrDefault())"
|
||||
SourceTable="selectedTable"
|
||||
DestinationType="rest"
|
||||
DestinationEndpoint="@(selectedRestEntity?.Name)"
|
||||
@@ -1149,62 +1149,6 @@
|
||||
OnProfileDeleted="OnProfileDeleted"
|
||||
IsLoading="isLoadingProfiles" />
|
||||
|
||||
<!-- Modal per la selezione del database -->
|
||||
@if (showDatabaseSelectionModal)
|
||||
{
|
||||
<div class="modal fade show d-block" style="background-color: rgba(0,0,0,0.5);">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="fas fa-database"></i> Seleziona Database
|
||||
</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="text-muted">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
Sono stati trovati più database nel server. Seleziona il database da utilizzare:
|
||||
</p>
|
||||
|
||||
@if (availableDatabases != null && availableDatabases.Any())
|
||||
{
|
||||
<div class="mb-3">
|
||||
<label for="databaseSelect" class="form-label">Database disponibili:</label>
|
||||
<select id="databaseSelect" class="form-select" @bind="selectedDatabase">
|
||||
<option value="">-- Seleziona un database --</option>
|
||||
@foreach (var db in availableDatabases)
|
||||
{
|
||||
<option value="@db">@db</option>
|
||||
}
|
||||
</select>
|
||||
<small class="form-text text-muted">
|
||||
<i class="fas fa-lightbulb"></i>
|
||||
Il database determina quali tabelle e viste saranno disponibili per il mapping.
|
||||
</small>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="alert alert-warning">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
Nessun database trovato o errore nel caricamento.
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @onclick="CancelDatabaseSelection">
|
||||
<i class="fas fa-times"></i> Annulla
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="OnDatabaseSelected"
|
||||
disabled="@string.IsNullOrEmpty(selectedDatabase)">
|
||||
<i class="fas fa-check"></i> Connetti al Database
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Modal per la selezione dello schema -->
|
||||
@if (showSchemaSelectionModal)
|
||||
{
|
||||
@@ -1267,3 +1211,60 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Modal per la selezione del database -->
|
||||
@if (showDatabaseSelectionModal)
|
||||
{
|
||||
<div class="modal fade show d-block" style="background-color: rgba(0,0,0,0.5);">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="fas fa-database"></i> Seleziona Database
|
||||
</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="text-muted">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
La connessione non specifica un database. Seleziona il database da esplorare:
|
||||
</p>
|
||||
@if (isLoadingDatabases)
|
||||
{
|
||||
<div class="text-center">
|
||||
<div class="spinner-border spinner-border-sm me-2"></div>
|
||||
Caricamento database...
|
||||
</div>
|
||||
}
|
||||
else if (availableDatabases != null && availableDatabases.Any())
|
||||
{
|
||||
<div class="mb-3">
|
||||
<label for="databaseSelect" class="form-label">Database disponibili:</label>
|
||||
<select id="databaseSelect" class="form-select" @bind="selectedDatabase">
|
||||
<option value="">-- Seleziona un database --</option>
|
||||
@foreach (var db in availableDatabases)
|
||||
{
|
||||
<option value="@db">@db</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="alert alert-warning">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
Nessun database trovato o errore nel caricamento.
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @onclick="CancelDatabaseSelection">
|
||||
<i class="fas fa-times"></i> Annulla
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="OnDatabaseSelected" disabled="@string.IsNullOrEmpty(selectedDatabase)">
|
||||
<i class="fas fa-check"></i> Connetti con Database
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -57,19 +57,21 @@ public partial class DataCoupler : ComponentBase
|
||||
private string restErrorMessage = "";
|
||||
|
||||
// Database discovery
|
||||
private Dictionary<string, IEnumerable<DbColumnInfo>> databaseTables = new();
|
||||
private List<string> availableTableNames = new(); // Solo nomi delle tabelle
|
||||
private Dictionary<string, IEnumerable<DbColumnInfo>> databaseTables = new(); // Schema dettagliato per tabelle caricate
|
||||
private string selectedTable = "";
|
||||
private string databaseSearchTerm = "";
|
||||
|
||||
// Database selection
|
||||
// Database selection - per gestire la selezione del database quando non specificato nella connection string
|
||||
private List<string> availableDatabases = new();
|
||||
private List<string> availableSchemas = new();
|
||||
private string selectedDatabase = "";
|
||||
private string selectedSchema = "";
|
||||
private bool showDatabaseSelection = false;
|
||||
private bool showDatabaseSelectionModal = false;
|
||||
private bool showSchemaSelectionModal = false;
|
||||
private bool isLoadingDatabases = false;
|
||||
|
||||
// Database selection (schemas only)
|
||||
private List<string> availableSchemas = new();
|
||||
private string selectedSchema = "";
|
||||
private bool showSchemaSelectionModal = false;
|
||||
private bool isLoadingSchemas = false;
|
||||
|
||||
// Custom query functionality
|
||||
@@ -110,7 +112,6 @@ public partial class DataCoupler : ComponentBase
|
||||
private string sourceKeyField = ""; // Campo che identifica univocamente il record sorgente
|
||||
private string suggestedPrimaryKey = ""; // Campo PK suggerito per database
|
||||
private bool requiresManualKeySelection = false; // Flag per indicare se è richiesta selezione manuale
|
||||
private Dictionary<string, string> sourceKeyMappings = new(); // Per CSV: mapppatura colonna -> nome campo chiave
|
||||
private bool useRecordAssociations = true; // Se utilizzare il sistema di associazioni
|
||||
|
||||
// Trasferimento dati
|
||||
@@ -745,6 +746,12 @@ public partial class DataCoupler : ComponentBase
|
||||
databaseSearchTerm = "";
|
||||
databaseErrorMessage = "";
|
||||
|
||||
// Reset database selection
|
||||
availableDatabases.Clear();
|
||||
selectedDatabase = "";
|
||||
showDatabaseSelectionModal = false;
|
||||
isLoadingDatabases = false;
|
||||
|
||||
// Reset custom query state
|
||||
useCustomQuery = false;
|
||||
customQuery = "";
|
||||
@@ -774,7 +781,7 @@ public partial class DataCoupler : ComponentBase
|
||||
|
||||
// Clear mappings when resetting REST state
|
||||
ClearAllMappings();
|
||||
}private async Task ConnectToDatabase()
|
||||
} private async Task ConnectToDatabase()
|
||||
{
|
||||
if (string.IsNullOrEmpty(selectedDatabaseCredential))
|
||||
return;
|
||||
@@ -783,7 +790,8 @@ public partial class DataCoupler : ComponentBase
|
||||
databaseErrorMessage = "";
|
||||
|
||||
try
|
||||
{ // Trova la credenziale
|
||||
{
|
||||
// Trova la credenziale
|
||||
var credential = databaseCredentials.FirstOrDefault(c => c.Name == selectedDatabaseCredential);
|
||||
if (credential == null)
|
||||
{
|
||||
@@ -797,42 +805,51 @@ public partial class DataCoupler : ComponentBase
|
||||
{
|
||||
databaseErrorMessage = $"Connessione fallita: {message}";
|
||||
return;
|
||||
} // Crea il database manager usando il factory con le credenziali complete
|
||||
}
|
||||
|
||||
// Crea il database manager usando il factory con le credenziali complete
|
||||
Logger.LogInformation("Creando database manager per credenziale: {CredentialName}", selectedDatabaseCredential);
|
||||
currentDatabaseManager = await ConnectionFactory.CreateDatabaseManagerAsync(selectedDatabaseCredential);
|
||||
Logger.LogInformation("Database manager creato con successo");
|
||||
|
||||
Logger.LogInformation("Iniziando discovery dello schema per database {DatabaseType} con credenziale: {CredentialName}", credential.DatabaseType, selectedDatabaseCredential);
|
||||
|
||||
// Discovery dello schema con try-catch specifico
|
||||
try
|
||||
// Verifica se il database è specificato nella connection string
|
||||
bool isDatabaseSpecified = await IsDatabaseSpecifiedInConnectionString(credential);
|
||||
|
||||
if (isDatabaseSpecified)
|
||||
{
|
||||
var schema = await currentDatabaseManager.GetDatabaseSchemaAsync();
|
||||
|
||||
Logger.LogInformation("Schema discovery completato. Tipo restituito: {SchemaType}, Numero elementi: {Count}",
|
||||
schema?.GetType().Name ?? "null",
|
||||
schema?.Count() ?? 0);
|
||||
|
||||
databaseTables = schema as Dictionary<string, IEnumerable<DbColumnInfo>> ??
|
||||
(schema != null ? new Dictionary<string, IEnumerable<DbColumnInfo>>(schema) : new Dictionary<string, IEnumerable<DbColumnInfo>>());
|
||||
|
||||
Logger.LogInformation("Database tables dopo conversione: {Count} tabelle", databaseTables.Count);
|
||||
|
||||
if (databaseTables.Count == 0)
|
||||
Logger.LogInformation("Database specificato nella connection string. Procedendo con discovery tabelle.");
|
||||
try
|
||||
{
|
||||
// Se non ci sono tabelle, potrebbe essere perché non è stato selezionato un database specifico
|
||||
HandleDatabaseSelectionRequired();
|
||||
await LoadTablesFromConnectedDatabase();
|
||||
isDatabaseConnected = true;
|
||||
Logger.LogInformation("Tabelle caricate con successo, database connesso");
|
||||
return; // Importante: usciamo qui se tutto va bene
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nel caricamento tabelle dal database specificato");
|
||||
databaseErrorMessage = $"Errore nel caricamento tabelle: {ex.Message}";
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception schemaEx)
|
||||
else
|
||||
{
|
||||
Logger.LogError(schemaEx, "Errore specifico durante lo schema discovery");
|
||||
databaseErrorMessage = $"Errore nello schema discovery: {schemaEx.Message}";
|
||||
throw;
|
||||
Logger.LogInformation("Database non specificato nella connection string. Caricando database disponibili.");
|
||||
await LoadAvailableDatabases();
|
||||
|
||||
if (availableDatabases.Any())
|
||||
{
|
||||
Logger.LogInformation("Trovati {DatabaseCount} database disponibili", availableDatabases.Count);
|
||||
showDatabaseSelectionModal = true;
|
||||
StateHasChanged();
|
||||
return; // Non procediamo fino alla selezione del database
|
||||
}
|
||||
else
|
||||
{
|
||||
databaseErrorMessage = "Nessun database disponibile trovato";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
isDatabaseConnected = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -842,8 +859,9 @@ public partial class DataCoupler : ComponentBase
|
||||
finally
|
||||
{
|
||||
isConnectingDatabase = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
} private async Task ConnectToRestApi()
|
||||
}private async Task ConnectToRestApi()
|
||||
{
|
||||
if (string.IsNullOrEmpty(selectedRestCredential))
|
||||
return;
|
||||
@@ -926,6 +944,21 @@ public partial class DataCoupler : ComponentBase
|
||||
suggestedPrimaryKey = "";
|
||||
requiresManualKeySelection = false;
|
||||
|
||||
// Carica i dettagli della tabella se non sono già stati caricati
|
||||
if (!databaseTables.ContainsKey(tableName) && currentDatabaseManager != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var tableSchema = await currentDatabaseManager.GetTableSchemaAsync(tableName);
|
||||
databaseTables[tableName] = tableSchema;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nel caricamento dello schema della tabella {TableName}", tableName);
|
||||
databaseErrorMessage = $"Errore nel caricamento della tabella: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a database source, try to detect the primary key
|
||||
if (selectedSourceType == "database" && currentDatabaseManager != null)
|
||||
{
|
||||
@@ -987,9 +1020,9 @@ public partial class DataCoupler : ComponentBase
|
||||
private IEnumerable<string> GetFilteredDatabaseTables()
|
||||
{
|
||||
if (string.IsNullOrEmpty(databaseSearchTerm))
|
||||
return databaseTables.Keys;
|
||||
return availableTableNames;
|
||||
|
||||
return databaseTables.Keys.Where(table =>
|
||||
return availableTableNames.Where(table =>
|
||||
table.Contains(databaseSearchTerm, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
@@ -1864,7 +1897,8 @@ public partial class DataCoupler : ComponentBase
|
||||
if (databaseTables.Count == 0)
|
||||
{
|
||||
// Se non ci sono tabelle, potrebbe essere necessario selezionare un database specifico
|
||||
HandleDatabaseSelectionRequired();
|
||||
// Schema discovery completato senza successo
|
||||
databaseErrorMessage = "Impossibile rilevare le tabelle del database. Verificare le credenziali di connessione.";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1923,50 +1957,6 @@ public partial class DataCoupler : ComponentBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gestisce la situazione quando è richiesta la selezione di un database o schema specifico
|
||||
/// </summary>
|
||||
private async void HandleDatabaseSelectionRequired()
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInformation("Schema discovery non ha restituito risultati. Tentativo di scoprire database disponibili...");
|
||||
|
||||
// Prima prova a ottenere la lista dei database disponibili
|
||||
await LoadAvailableDatabases();
|
||||
|
||||
if (availableDatabases.Any())
|
||||
{
|
||||
// Se abbiamo database disponibili, mostra il modal per la selezione del database
|
||||
Logger.LogInformation("Trovati {DatabaseCount} database disponibili", availableDatabases.Count);
|
||||
showDatabaseSelectionModal = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Se non ci sono database, prova con gli schemi
|
||||
await LoadAvailableSchemas();
|
||||
|
||||
if (availableSchemas.Any())
|
||||
{
|
||||
Logger.LogInformation("Trovati {SchemaCount} schemi disponibili", availableSchemas.Count);
|
||||
showSchemaSelectionModal = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nessuna opzione disponibile
|
||||
databaseErrorMessage = "Impossibile rilevare database o schemi. Verificare le credenziali di connessione o il tipo di database.";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nella gestione della selezione database/schema");
|
||||
databaseErrorMessage = $"Errore nella rilevazione di database/schemi: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estrae lo schema dal nome completo di una tabella
|
||||
/// </summary>
|
||||
@@ -2195,7 +2185,7 @@ public partial class DataCoupler : ComponentBase
|
||||
{
|
||||
return databaseType switch
|
||||
{
|
||||
DatabaseType.SqlServer => $"SELECT TOP {limit} * FROM ({baseQuery}) AS subquery",
|
||||
DatabaseType.SqlServer => $"SELECT TOP {limit} * FROM ({baseQuery}) AS subquery",
|
||||
DatabaseType.Oracle => $"SELECT * FROM ({baseQuery}) WHERE ROWNUM <= {limit}",
|
||||
DatabaseType.MySql => $"{baseQuery} LIMIT {limit}",
|
||||
DatabaseType.PostgreSql => $"{baseQuery} LIMIT {limit}",
|
||||
@@ -2235,16 +2225,6 @@ public partial class DataCoupler : ComponentBase
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Annulla la selezione del database
|
||||
/// </summary>
|
||||
private void CancelDatabaseSelection()
|
||||
{
|
||||
showDatabaseSelectionModal = false;
|
||||
selectedDatabase = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Annulla la selezione dello schema
|
||||
/// </summary>
|
||||
@@ -2255,106 +2235,6 @@ public partial class DataCoupler : ComponentBase
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conferma la selezione del database
|
||||
/// </summary>
|
||||
private async Task OnDatabaseSelected()
|
||||
{
|
||||
if (string.IsNullOrEmpty(selectedDatabase))
|
||||
return;
|
||||
|
||||
showDatabaseSelectionModal = false;
|
||||
|
||||
try
|
||||
{
|
||||
Logger.LogInformation("Database selezionato: {Database}. Tentativo di connessione diretta...", selectedDatabase);
|
||||
|
||||
// Trova la credenziale corrente
|
||||
var credential = databaseCredentials.FirstOrDefault(c => c.Name == selectedDatabaseCredential);
|
||||
if (credential == null)
|
||||
{
|
||||
databaseErrorMessage = "Credenziale database non trovata";
|
||||
return;
|
||||
}
|
||||
|
||||
isConnectingDatabase = true;
|
||||
databaseErrorMessage = "";
|
||||
|
||||
// Disponi il manager precedente
|
||||
currentDatabaseManager?.Dispose();
|
||||
currentDatabaseManager = null;
|
||||
|
||||
// Per ora, proviamo a usare il database manager esistente e cercare le tabelle con query dirette
|
||||
// TODO: In futuro, modificare il ConnectionFactory per supportare database specifici
|
||||
currentDatabaseManager = await ConnectionFactory.CreateDatabaseManagerAsync(selectedDatabaseCredential);
|
||||
|
||||
// Prova a ottenere le tabelle del database specifico usando query dirette
|
||||
var tablesQuery = credential.DatabaseType switch
|
||||
{
|
||||
DatabaseType.SqlServer => $"SELECT TABLE_NAME FROM {selectedDatabase}.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'",
|
||||
DatabaseType.MySql => $"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{selectedDatabase}' AND TABLE_TYPE = 'BASE TABLE'",
|
||||
DatabaseType.PostgreSql => $"SELECT tablename as TABLE_NAME FROM pg_tables WHERE schemaname = '{selectedDatabase}'",
|
||||
DatabaseType.Oracle => $"SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = '{selectedDatabase.ToUpper()}'",
|
||||
_ => $"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{selectedDatabase}' AND TABLE_TYPE = 'BASE TABLE'"
|
||||
};
|
||||
|
||||
Logger.LogInformation("Eseguendo query per tabelle del database {Database}: {Query}", selectedDatabase, tablesQuery);
|
||||
|
||||
var tableResults = await currentDatabaseManager.ExecuteRawQueryAsync(tablesQuery);
|
||||
|
||||
if (tableResults != null && tableResults.Any())
|
||||
{
|
||||
// Converte i risultati in un dizionario di tabelle
|
||||
databaseTables.Clear();
|
||||
|
||||
foreach (var row in tableResults)
|
||||
{
|
||||
var tableName = row.Values.FirstOrDefault()?.ToString();
|
||||
if (!string.IsNullOrEmpty(tableName))
|
||||
{
|
||||
// Per ogni tabella, prova a ottenere le colonne
|
||||
try
|
||||
{
|
||||
var fullTableName = credential.DatabaseType == DatabaseType.SqlServer
|
||||
? $"{selectedDatabase}.dbo.{tableName}"
|
||||
: $"{selectedDatabase}.{tableName}";
|
||||
|
||||
var columns = await GetTableColumns(fullTableName, selectedDatabase, tableName);
|
||||
databaseTables[fullTableName] = columns;
|
||||
}
|
||||
catch (Exception colEx)
|
||||
{
|
||||
Logger.LogWarning(colEx, "Impossibile ottenere colonne per la tabella {TableName}", tableName);
|
||||
// Aggiungi la tabella anche senza colonne specifiche
|
||||
databaseTables[tableName] = new List<DbColumnInfo>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isDatabaseConnected = true;
|
||||
Logger.LogInformation("Connessione completata con successo. Database: {Database}, Tabelle: {TableCount}",
|
||||
selectedDatabase, databaseTables.Count);
|
||||
databaseErrorMessage = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
databaseErrorMessage = $"Nessuna tabella trovata nel database {selectedDatabase}";
|
||||
Logger.LogWarning("Nessuna tabella trovata nel database {Database}", selectedDatabase);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nella connessione con il database selezionato: {Database}", selectedDatabase);
|
||||
databaseErrorMessage = $"Errore nella connessione con database {selectedDatabase}: {ex.Message}";
|
||||
isDatabaseConnected = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
isConnectingDatabase = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ottiene le colonne di una tabella specifica
|
||||
/// </summary>
|
||||
@@ -2583,62 +2463,249 @@ public partial class DataCoupler : ComponentBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carica la lista dei database disponibili
|
||||
/// </summary>
|
||||
private async Task LoadAvailableDatabases()
|
||||
// Gestione selezione database quando la discovery restituisce dizionario vuoto
|
||||
private async Task HandleDatabaseSelectionRequired()
|
||||
{
|
||||
if (currentDatabaseManager == null)
|
||||
return;
|
||||
|
||||
isLoadingDatabases = true;
|
||||
showDatabaseSelectionModal = true;
|
||||
availableDatabases.Clear();
|
||||
|
||||
selectedDatabase = "";
|
||||
try
|
||||
{
|
||||
var credential = databaseCredentials.FirstOrDefault(c => c.Name == selectedDatabaseCredential);
|
||||
if (credential == null) return;
|
||||
|
||||
string? databaseQuery = credential.DatabaseType switch
|
||||
if (currentDatabaseManager != null)
|
||||
{
|
||||
DatabaseType.SqlServer => "SELECT name FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb')",
|
||||
DatabaseType.PostgreSql => "SELECT datname FROM pg_database WHERE datistemplate = false AND datname NOT IN ('postgres', 'template0', 'template1')",
|
||||
DatabaseType.MySql => "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql', 'sys')",
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(databaseQuery))
|
||||
{
|
||||
var results = await currentDatabaseManager.ExecuteRawQueryAsync(databaseQuery);
|
||||
|
||||
if (results != null && results.Any())
|
||||
{
|
||||
var databases = results.Select(row =>
|
||||
{
|
||||
var firstValue = row.Values.FirstOrDefault();
|
||||
return firstValue?.ToString() ?? "";
|
||||
})
|
||||
.Where(db => !string.IsNullOrEmpty(db))
|
||||
.OrderBy(db => db)
|
||||
.ToList();
|
||||
|
||||
if (databases.Any())
|
||||
{
|
||||
availableDatabases.AddRange(databases);
|
||||
Logger.LogInformation("Caricati {DatabaseCount} database per {DatabaseType}: {Databases}",
|
||||
databases.Count, credential.DatabaseType, string.Join(", ", databases));
|
||||
}
|
||||
}
|
||||
var dbs = await currentDatabaseManager.GetAvailableDatabasesAsync();
|
||||
availableDatabases = dbs ?? new List<string>();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nel caricamento dei database disponibili");
|
||||
databaseErrorMessage = $"Errore nel caricamento dei database: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoadingDatabases = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnDatabaseSelected()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(selectedDatabase))
|
||||
{
|
||||
databaseErrorMessage = "Nessun database selezionato";
|
||||
return;
|
||||
}
|
||||
|
||||
showDatabaseSelectionModal = false;
|
||||
|
||||
Logger.LogInformation("Database selezionato: {DatabaseName}. Riconnessione in corso...", selectedDatabase);
|
||||
|
||||
// Riconnessione al database selezionato
|
||||
await ConnectToDatabaseWithSpecificDatabase(selectedDatabase);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nella selezione del database: {DatabaseName}", selectedDatabase);
|
||||
databaseErrorMessage = $"Errore nella connessione al database {selectedDatabase}: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelDatabaseSelection()
|
||||
{
|
||||
showDatabaseSelectionModal = false;
|
||||
selectedDatabase = "";
|
||||
databaseErrorMessage = "Selezione database annullata";
|
||||
Logger.LogInformation("Selezione database annullata dall'utente");
|
||||
}
|
||||
|
||||
// Metodi helper per la connessione database
|
||||
private Task<bool> IsDatabaseSpecifiedInConnectionString(DatabaseCredential credential)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.LogInformation("Verifica database specificato - Tipo: {DatabaseType}, DatabaseName: '{DatabaseName}', Connection: {ConnectionString}",
|
||||
credential.DatabaseType, credential.DatabaseName, credential.ConnectionString?.Substring(0, Math.Min(100, credential.ConnectionString?.Length ?? 0)));
|
||||
|
||||
// Prima verifica se c'è un database specificato nel campo DatabaseName della credenziale
|
||||
if (!string.IsNullOrEmpty(credential.DatabaseName))
|
||||
{
|
||||
Logger.LogInformation("Database specificato nel campo DatabaseName: '{DatabaseName}' - RESULT: TRUE", credential.DatabaseName);
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
// Per SQL Server verifica se Initial Catalog o Database è specificato nella connection string
|
||||
if (credential.DatabaseType == DatabaseType.SqlServer)
|
||||
{
|
||||
var connectionString = credential.ConnectionString ?? "";
|
||||
var hasInitialCatalog = connectionString.Contains("Initial Catalog=", StringComparison.OrdinalIgnoreCase);
|
||||
var hasDatabase = connectionString.Contains("Database=", StringComparison.OrdinalIgnoreCase);
|
||||
var result = hasInitialCatalog || hasDatabase;
|
||||
|
||||
Logger.LogInformation("SQL Server - HasInitialCatalog: {HasInitialCatalog}, HasDatabase: {HasDatabase}, Result: {Result}",
|
||||
hasInitialCatalog, hasDatabase, result);
|
||||
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
// TODO: Implementare per altri tipi di database
|
||||
// MySQL: Database=
|
||||
// PostgreSQL: Database=
|
||||
// Oracle: più complesso con SID/Service Name
|
||||
|
||||
Logger.LogWarning("Verifica database specificato non implementata per tipo database: {DatabaseType}", credential.DatabaseType);
|
||||
return Task.FromResult(true); // Default: assume database specificato per tipi non implementati
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nella verifica database specificato in connection string");
|
||||
return Task.FromResult(true); // Default: assume database specificato in caso di errore
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadTablesFromConnectedDatabase()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (currentDatabaseManager == null)
|
||||
{
|
||||
databaseErrorMessage = "Database manager non disponibile";
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInformation("Caricando tabelle dal database connesso");
|
||||
var tableNames = await currentDatabaseManager.GetTableNamesAsync();
|
||||
availableTableNames = tableNames.ToList();
|
||||
|
||||
Logger.LogInformation("Caricate {Count} tabelle dal database", availableTableNames.Count);
|
||||
|
||||
// Resetta i dettagli delle tabelle - verranno caricati solo quando selezionati
|
||||
databaseTables.Clear();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nel caricamento delle tabelle dal database connesso");
|
||||
databaseErrorMessage = $"Errore nel caricamento tabelle: {ex.Message}";
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadAvailableDatabases()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (currentDatabaseManager == null)
|
||||
{
|
||||
databaseErrorMessage = "Database manager non disponibile";
|
||||
return;
|
||||
}
|
||||
|
||||
isLoadingDatabases = true;
|
||||
Logger.LogInformation("Caricando database disponibili");
|
||||
|
||||
// Usa il metodo corretto dell'interfaccia IDatabaseManager
|
||||
var allDatabases = await currentDatabaseManager.GetAvailableDatabasesAsync();
|
||||
Logger.LogInformation("Ottenuti {DatabaseCount} database dal server", allDatabases.Count);
|
||||
|
||||
// Filtra i database di sistema
|
||||
availableDatabases = FilterSystemDatabases(allDatabases).ToList();
|
||||
|
||||
Logger.LogInformation("Trovati {TotalDatabases} database, filtrati a {FilteredDatabases} (esclusi quelli di sistema)",
|
||||
allDatabases.Count, availableDatabases.Count);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nel caricamento dei database disponibili");
|
||||
databaseErrorMessage = $"Errore nel caricamento database: {ex.Message}";
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoadingDatabases = false;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<string> FilterSystemDatabases(List<string> allDatabases)
|
||||
{
|
||||
// Trova la credenziale per determinare il tipo di database
|
||||
var credential = databaseCredentials.FirstOrDefault(c => c.Name == selectedDatabaseCredential);
|
||||
if (credential == null)
|
||||
{
|
||||
Logger.LogWarning("Credenziale non trovata per filtraggio database di sistema");
|
||||
return allDatabases; // Restituisce tutti se non riesce a determinare il tipo
|
||||
}
|
||||
|
||||
var databaseType = credential.DatabaseType;
|
||||
|
||||
// Filtri per SQL Server
|
||||
if (databaseType == DatabaseType.SqlServer)
|
||||
{
|
||||
var sqlServerSystemDatabases = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"master", "tempdb", "model", "msdb", "Resource", "mssqlsystemresource",
|
||||
"ReportServer", "ReportServerTempDB", "SSISDB", "distribution"
|
||||
};
|
||||
|
||||
return allDatabases.Where(db => !sqlServerSystemDatabases.Contains(db));
|
||||
}
|
||||
|
||||
// TODO: Implementare filtri per altri tipi di database
|
||||
if (databaseType == DatabaseType.MySql)
|
||||
{
|
||||
Logger.LogInformation("Filtro database di sistema MySQL - DA IMPLEMENTARE");
|
||||
return allDatabases; // Per ora restituisce tutti
|
||||
}
|
||||
|
||||
if (databaseType == DatabaseType.PostgreSql)
|
||||
{
|
||||
Logger.LogInformation("Filtro database di sistema PostgreSQL - DA IMPLEMENTARE");
|
||||
return allDatabases; // Per ora restituisce tutti
|
||||
}
|
||||
|
||||
if (databaseType == DatabaseType.Oracle)
|
||||
{
|
||||
Logger.LogInformation("Filtro database di sistema Oracle - DA IMPLEMENTARE");
|
||||
return allDatabases; // Per ora restituisce tutti
|
||||
}
|
||||
|
||||
Logger.LogWarning("Tipo database non riconosciuto per filtraggio: {DatabaseType}", databaseType);
|
||||
return allDatabases; // Restituisce tutti per tipi non riconosciuti
|
||||
}
|
||||
|
||||
// Metodo per gestire la selezione di un database dal modale
|
||||
|
||||
|
||||
private async Task ConnectToDatabaseWithSpecificDatabase(string databaseName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (currentDatabaseManager == null)
|
||||
{
|
||||
databaseErrorMessage = "Database manager non disponibile";
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInformation("Cambiando database a: {DatabaseName}", databaseName);
|
||||
|
||||
// Usa il metodo dell'interfaccia per cambiare database
|
||||
await currentDatabaseManager.ChangeDatabaseAsync(databaseName);
|
||||
Logger.LogInformation("Database cambiato con successo a: {DatabaseName}", databaseName);
|
||||
|
||||
// Carica le tabelle dal database selezionato
|
||||
await LoadTablesFromConnectedDatabase();
|
||||
|
||||
isDatabaseConnected = true;
|
||||
Logger.LogInformation("Connessione completata per database: {DatabaseName}", databaseName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nella connessione al database specifico: {DatabaseName}", databaseName);
|
||||
databaseErrorMessage = $"Errore nella connessione al database {databaseName}: {ex.Message}";
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user