Correzione selezione database/schema nell'interfaccia Data Coupler
- Implementato discovery intelligente database vs schemi per ogni DBMS - Aggiornate query SQL per mostrare solo database effettivi (non ruoli/schemi di sistema) - Aggiunta UI modal per selezione database con riconnessione automatica - Aggiunta UI modal fallback per selezione schema quando necessario - Migliorate query discovery per SQL Server, PostgreSQL, MySQL e Oracle - Implementata logica di riconnessione automatica al database selezionato - Aggiornati testi e descrizioni dell'interfaccia per maggiore chiarezza - Gestione prioritaria: database disponibili fallback su schemi se necessario Fixes: Menu selezione mostrava ruoli invece dei database reali
This commit is contained in:
@@ -1155,7 +1155,7 @@
|
||||
<div class="modal-body">
|
||||
<p class="text-muted">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
Il server non ha un database predefinito. Seleziona il database su cui eseguire le operazioni:
|
||||
Sono stati trovati più database nel server. Seleziona il database da utilizzare:
|
||||
</p>
|
||||
|
||||
@if (availableDatabases != null && availableDatabases.Any())
|
||||
@@ -1169,6 +1169,10 @@
|
||||
<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
|
||||
@@ -1185,7 +1189,70 @@
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="OnDatabaseSelected"
|
||||
disabled="@string.IsNullOrEmpty(selectedDatabase)">
|
||||
<i class="fas fa-check"></i> Conferma
|
||||
<i class="fas fa-check"></i> Connetti al Database
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Modal per la selezione dello schema -->
|
||||
@if (showSchemaSelectionModal)
|
||||
{
|
||||
<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-sitemap"></i> Seleziona Schema
|
||||
</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="text-muted">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
Sono stati trovati più schemi nel database. Seleziona lo schema da utilizzare:
|
||||
</p>
|
||||
|
||||
@if (isLoadingSchemas)
|
||||
{
|
||||
<div class="text-center">
|
||||
<div class="spinner-border spinner-border-sm me-2"></div>
|
||||
Caricamento schemi...
|
||||
</div>
|
||||
}
|
||||
else if (availableSchemas != null && availableSchemas.Any())
|
||||
{
|
||||
<div class="mb-3">
|
||||
<label for="schemaSelect" class="form-label">Schemi disponibili:</label>
|
||||
<select id="schemaSelect" class="form-select" @bind="selectedSchema">
|
||||
<option value="">-- Seleziona uno schema --</option>
|
||||
@foreach (var schema in availableSchemas)
|
||||
{
|
||||
<option value="@schema">@schema</option>
|
||||
}
|
||||
</select>
|
||||
<small class="form-text text-muted">
|
||||
<i class="fas fa-lightbulb"></i>
|
||||
Lo schema 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>
|
||||
Nessuno schema trovato o errore nel caricamento.
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @onclick="CancelSchemaSelection">
|
||||
<i class="fas fa-times"></i> Annulla
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="OnSchemaSelected"
|
||||
disabled="@string.IsNullOrEmpty(selectedSchema)">
|
||||
<i class="fas fa-check"></i> Connetti con Schema
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,10 +53,14 @@ public partial class DataCoupler
|
||||
|
||||
// Database selection
|
||||
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;
|
||||
private bool isLoadingSchemas = false;
|
||||
|
||||
// Custom query functionality
|
||||
private bool useCustomQuery = false;
|
||||
@@ -1910,23 +1914,46 @@ public partial class DataCoupler
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gestisce la situazione quando è richiesta la selezione di un database specifico
|
||||
/// Gestisce la situazione quando è richiesta la selezione di un database o schema specifico
|
||||
/// </summary>
|
||||
private void HandleDatabaseSelectionRequired()
|
||||
private async void HandleDatabaseSelectionRequired()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Prova a ottenere la lista dei database disponibili
|
||||
// TODO: Implementare se il DatabaseManager supporta GetAvailableDatabases
|
||||
Logger.LogInformation("Database selection richiesta - implementazione da completare");
|
||||
Logger.LogInformation("Schema discovery non ha restituito risultati. Tentativo di scoprire database disponibili...");
|
||||
|
||||
// Per ora, impostiamo un messaggio di errore informativo
|
||||
databaseErrorMessage = "Schema discovery non ha restituito risultati. Potrebbe essere necessario specificare un database o schema specifico nella connessione.";
|
||||
// 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");
|
||||
databaseErrorMessage = $"Errore nella selezione database: {ex.Message}";
|
||||
Logger.LogError(ex, "Errore nella gestione della selezione database/schema");
|
||||
databaseErrorMessage = $"Errore nella rilevazione di database/schemi: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2166,6 +2193,16 @@ public partial class DataCoupler
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Annulla la selezione dello schema
|
||||
/// </summary>
|
||||
private void CancelSchemaSelection()
|
||||
{
|
||||
showSchemaSelectionModal = false;
|
||||
selectedSchema = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conferma la selezione del database
|
||||
/// </summary>
|
||||
@@ -2178,19 +2215,225 @@ public partial class DataCoupler
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: Implementare la logica per connettersi al database selezionato
|
||||
Logger.LogInformation("Database selezionato: {Database}", selectedDatabase);
|
||||
Logger.LogInformation("Database selezionato: {Database}. Riconnessione al database...", selectedDatabase);
|
||||
|
||||
// Per ora, chiudi semplicemente il dialog
|
||||
await Task.CompletedTask;
|
||||
// Riconnetti al database utilizzando il database selezionato come schema
|
||||
await ConnectToDatabaseWithSchema(selectedDatabase);
|
||||
|
||||
if (isDatabaseConnected)
|
||||
{
|
||||
Logger.LogInformation("Connessione completata con successo usando il database {Database}", selectedDatabase);
|
||||
databaseErrorMessage = ""; // Pulisci eventuali errori precedenti
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nella selezione del database");
|
||||
databaseErrorMessage = $"Errore nella selezione database: {ex.Message}";
|
||||
Logger.LogError(ex, "Errore nella connessione con il database selezionato");
|
||||
databaseErrorMessage = $"Errore nella connessione con database {selectedDatabase}: {ex.Message}";
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conferma la selezione dello schema
|
||||
/// </summary>
|
||||
private async Task OnSchemaSelected()
|
||||
{
|
||||
if (string.IsNullOrEmpty(selectedSchema))
|
||||
return;
|
||||
|
||||
showSchemaSelectionModal = false;
|
||||
|
||||
try
|
||||
{
|
||||
Logger.LogInformation("Schema selezionato: {Schema}. Riconnessione al database...", selectedSchema);
|
||||
|
||||
// Riconnetti al database utilizzando lo schema selezionato
|
||||
await ConnectToDatabaseWithSchema(selectedSchema);
|
||||
|
||||
if (isDatabaseConnected)
|
||||
{
|
||||
Logger.LogInformation("Connessione completata con successo usando lo schema {Schema}", selectedSchema);
|
||||
databaseErrorMessage = ""; // Pulisci eventuali errori precedenti
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nella connessione con lo schema selezionato");
|
||||
databaseErrorMessage = $"Errore nella connessione con schema {selectedSchema}: {ex.Message}";
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carica la lista degli schemi disponibili
|
||||
/// </summary>
|
||||
private async Task LoadAvailableSchemas()
|
||||
{
|
||||
if (currentDatabaseManager == null)
|
||||
return;
|
||||
|
||||
isLoadingSchemas = true;
|
||||
availableSchemas.Clear();
|
||||
|
||||
try
|
||||
{
|
||||
// Prova a ottenere tutti gli schemi/database disponibili
|
||||
// Questo metodo potrebbe non essere disponibile su tutti i database manager
|
||||
// In tal caso, proveremo con una query diretta
|
||||
try
|
||||
{
|
||||
var allSchemas = await currentDatabaseManager.GetDatabaseSchemaAsync();
|
||||
|
||||
if (allSchemas != null)
|
||||
{
|
||||
// Estrai i nomi degli schemi dalle chiavi delle tabelle
|
||||
var schemaNames = allSchemas.Keys
|
||||
.Where(key => key.Contains('.'))
|
||||
.Select(key => key.Split('.')[0])
|
||||
.Distinct()
|
||||
.OrderBy(schema => schema)
|
||||
.ToList();
|
||||
|
||||
if (schemaNames.Any())
|
||||
{
|
||||
availableSchemas.AddRange(schemaNames);
|
||||
Logger.LogInformation("Rilevati {SchemaCount} schemi dalle tabelle: {Schemas}",
|
||||
schemaNames.Count, string.Join(", ", schemaNames));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Impossibile ottenere schemi dal database manager, provo con query dirette");
|
||||
}
|
||||
|
||||
// Se il metodo sopra non funziona, prova con query SQL specifiche per database
|
||||
await TryLoadSchemasWithDirectQuery();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nel caricamento degli schemi disponibili");
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoadingSchemas = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prova a caricare gli schemi con query SQL dirette
|
||||
/// </summary>
|
||||
private async Task TryLoadSchemasWithDirectQuery()
|
||||
{
|
||||
if (currentDatabaseManager == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// Query diverse per ogni tipo di database - focalizzate sui database/cataloghi
|
||||
var credential = databaseCredentials.FirstOrDefault(c => c.Name == selectedDatabaseCredential);
|
||||
if (credential == null) return;
|
||||
|
||||
string? schemaQuery = credential.DatabaseType switch
|
||||
{
|
||||
DatabaseType.SqlServer => "SELECT name FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb') AND state = 0",
|
||||
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')",
|
||||
DatabaseType.Oracle => "SELECT DISTINCT OWNER FROM ALL_TABLES WHERE OWNER NOT IN ('SYS', 'SYSTEM', 'DBSNMP', 'SYSMAN', 'OUTLN', 'ANONYMOUS', 'CTXSYS', 'EXFSYS', 'LBACSYS', 'MDSYS', 'MGMT_VIEW', 'OLAPSYS', 'OWBSYS', 'ORDDATA', 'ORDSYS', 'SI_INFORMTN_SCHEMA', 'WK_TEST', 'WKPROXY', 'WMSYS', 'XDB', 'APEX_040000', 'APEX_PUBLIC_USER', 'DIP', 'FLOWS_FILES', 'HR', 'IX', 'OE', 'PM', 'SCOTT', 'SH', 'BI')",
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(schemaQuery))
|
||||
{
|
||||
Logger.LogInformation("Eseguendo query per database/schemi: {Query}", schemaQuery);
|
||||
var results = await currentDatabaseManager.ExecuteRawQueryAsync(schemaQuery);
|
||||
|
||||
if (results != null && results.Any())
|
||||
{
|
||||
var schemas = results.Select(row =>
|
||||
{
|
||||
var firstValue = row.Values.FirstOrDefault();
|
||||
return firstValue?.ToString() ?? "";
|
||||
})
|
||||
.Where(schema => !string.IsNullOrEmpty(schema))
|
||||
.OrderBy(schema => schema)
|
||||
.ToList();
|
||||
|
||||
if (schemas.Any())
|
||||
{
|
||||
availableSchemas.AddRange(schemas);
|
||||
Logger.LogInformation("Caricati {SchemaCount} database/schemi via query diretta per {DatabaseType}: {Schemas}",
|
||||
schemas.Count, credential.DatabaseType, string.Join(", ", schemas));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Errore nel caricamento database/schemi via query diretta");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carica la lista dei database disponibili
|
||||
/// </summary>
|
||||
private async Task LoadAvailableDatabases()
|
||||
{
|
||||
if (currentDatabaseManager == null)
|
||||
return;
|
||||
|
||||
isLoadingDatabases = true;
|
||||
availableDatabases.Clear();
|
||||
|
||||
try
|
||||
{
|
||||
var credential = databaseCredentials.FirstOrDefault(c => c.Name == selectedDatabaseCredential);
|
||||
if (credential == null) return;
|
||||
|
||||
string? databaseQuery = credential.DatabaseType switch
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nel caricamento dei database disponibili");
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoadingDatabases = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user