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">
|
<div class="modal-body">
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
<i class="fas fa-info-circle"></i>
|
<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>
|
</p>
|
||||||
|
|
||||||
@if (availableDatabases != null && availableDatabases.Any())
|
@if (availableDatabases != null && availableDatabases.Any())
|
||||||
@@ -1169,6 +1169,10 @@
|
|||||||
<option value="@db">@db</option>
|
<option value="@db">@db</option>
|
||||||
}
|
}
|
||||||
</select>
|
</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>
|
</div>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1185,7 +1189,70 @@
|
|||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-primary" @onclick="OnDatabaseSelected"
|
<button type="button" class="btn btn-primary" @onclick="OnDatabaseSelected"
|
||||||
disabled="@string.IsNullOrEmpty(selectedDatabase)">
|
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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -53,10 +53,14 @@ public partial class DataCoupler
|
|||||||
|
|
||||||
// Database selection
|
// Database selection
|
||||||
private List<string> availableDatabases = new();
|
private List<string> availableDatabases = new();
|
||||||
|
private List<string> availableSchemas = new();
|
||||||
private string selectedDatabase = "";
|
private string selectedDatabase = "";
|
||||||
|
private string selectedSchema = "";
|
||||||
private bool showDatabaseSelection = false;
|
private bool showDatabaseSelection = false;
|
||||||
private bool showDatabaseSelectionModal = false;
|
private bool showDatabaseSelectionModal = false;
|
||||||
|
private bool showSchemaSelectionModal = false;
|
||||||
private bool isLoadingDatabases = false;
|
private bool isLoadingDatabases = false;
|
||||||
|
private bool isLoadingSchemas = false;
|
||||||
|
|
||||||
// Custom query functionality
|
// Custom query functionality
|
||||||
private bool useCustomQuery = false;
|
private bool useCustomQuery = false;
|
||||||
@@ -1910,23 +1914,46 @@ public partial class DataCoupler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
private void HandleDatabaseSelectionRequired()
|
private async void HandleDatabaseSelectionRequired()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Prova a ottenere la lista dei database disponibili
|
Logger.LogInformation("Schema discovery non ha restituito risultati. Tentativo di scoprire database disponibili...");
|
||||||
// TODO: Implementare se il DatabaseManager supporta GetAvailableDatabases
|
|
||||||
Logger.LogInformation("Database selection richiesta - implementazione da completare");
|
|
||||||
|
|
||||||
// Per ora, impostiamo un messaggio di errore informativo
|
// Prima prova a ottenere la lista dei database disponibili
|
||||||
databaseErrorMessage = "Schema discovery non ha restituito risultati. Potrebbe essere necessario specificare un database o schema specifico nella connessione.";
|
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)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError(ex, "Errore nella gestione della selezione database");
|
Logger.LogError(ex, "Errore nella gestione della selezione database/schema");
|
||||||
databaseErrorMessage = $"Errore nella selezione database: {ex.Message}";
|
databaseErrorMessage = $"Errore nella rilevazione di database/schemi: {ex.Message}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2166,6 +2193,16 @@ public partial class DataCoupler
|
|||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Annulla la selezione dello schema
|
||||||
|
/// </summary>
|
||||||
|
private void CancelSchemaSelection()
|
||||||
|
{
|
||||||
|
showSchemaSelectionModal = false;
|
||||||
|
selectedSchema = "";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Conferma la selezione del database
|
/// Conferma la selezione del database
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2178,19 +2215,225 @@ public partial class DataCoupler
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO: Implementare la logica per connettersi al database selezionato
|
Logger.LogInformation("Database selezionato: {Database}. Riconnessione al database...", selectedDatabase);
|
||||||
Logger.LogInformation("Database selezionato: {Database}", selectedDatabase);
|
|
||||||
|
|
||||||
// Per ora, chiudi semplicemente il dialog
|
// Riconnetti al database utilizzando il database selezionato come schema
|
||||||
await Task.CompletedTask;
|
await ConnectToDatabaseWithSchema(selectedDatabase);
|
||||||
|
|
||||||
|
if (isDatabaseConnected)
|
||||||
|
{
|
||||||
|
Logger.LogInformation("Connessione completata con successo usando il database {Database}", selectedDatabase);
|
||||||
|
databaseErrorMessage = ""; // Pulisci eventuali errori precedenti
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError(ex, "Errore nella selezione del database");
|
Logger.LogError(ex, "Errore nella connessione con il database selezionato");
|
||||||
databaseErrorMessage = $"Errore nella selezione database: {ex.Message}";
|
databaseErrorMessage = $"Errore nella connessione con database {selectedDatabase}: {ex.Message}";
|
||||||
}
|
}
|
||||||
|
|
||||||
StateHasChanged();
|
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