Files
Data-Coupler/ODBC_CUSTOM_QUERY_ONLY.md
T
2026-02-03 09:27:23 +01:00

11 KiB

Implementazione ODBC Query Custom Only

📋 Panoramica

Data la natura generica dei driver ODBC e le limitazioni del discovery automatico delle tabelle, è stato implementato un comportamento speciale per le connessioni ODBC nel DataCoupler: le connessioni ODBC utilizzano esclusivamente query SQL custom, bypassando completamente il sistema di discovery delle tabelle.

🎯 Motivazione

I driver ODBC sono estremamente eterogenei e spesso:

  • Non supportano query standard di discovery delle tabelle
  • Hanno sintassi SQL non standardizzate
  • Richiedono permessi specifici per accedere ai metadati del database
  • Possono avere limitazioni sulla lettura dello schema

Per questi motivi, è più sicuro e affidabile richiedere all'utente di specificare direttamente la query SQL da eseguire.

🔧 Modifiche Implementate

1. DatabaseMethod.cs

Nuovo Metodo Helper: IsOdbcConnection()

/// <summary>
/// Verifica se la credenziale database selezionata è di tipo ODBC
/// </summary>
/// <returns>True se la credenziale è ODBC, altrimenti False</returns>
protected bool IsOdbcConnection()
{
    if (string.IsNullOrEmpty(selectedDatabaseCredential))
        return false;
    
    var credential = databaseCredentials.FirstOrDefault(c => c.Name == selectedDatabaseCredential);
    return credential?.DatabaseType == DatabaseType.Odbc;
}

Funzionalità:

  • Verifica rapidamente se la credenziale corrente è ODBC
  • Utilizzato in tutta l'UI per condizionare la visualizzazione degli elementi

Modificato: OnDatabaseCredentialChanged()

protected void OnDatabaseCredentialChanged(ChangeEventArgs e)
{
    selectedDatabaseCredential = e.Value?.ToString() ?? "";
    ResetDatabaseState();
    
    // Se è una connessione ODBC, forza l'uso di query custom
    if (IsOdbcConnection())
    {
        useCustomQuery = true;
    }
}

Comportamento:

  • Quando l'utente seleziona una credenziale ODBC, useCustomQuery viene automaticamente impostato a true
  • Questo forza l'applicazione a mostrare solo la sezione query custom

Modificato: ValidateCustomQuery()

Problema originale: Il metodo richiedeva currentDatabaseManager già creato, ma per ODBC non si fa connessione preliminare.

Soluzione implementata:

protected async Task ValidateCustomQuery()
{
    // ...
    IDatabaseManager? tempManager = null;
    
    try
    {
        // Per ODBC, crea un database manager temporaneo se non esiste
        var managerToUse = currentDatabaseManager;
        if (managerToUse == null && IsOdbcConnection())
        {
            Logger.LogInformation("Creando database manager temporaneo per validazione query ODBC");
            tempManager = await ConnectionFactory.CreateDatabaseManagerAsync(selectedDatabaseCredential);
            managerToUse = tempManager;
        }
        
        // Valida la query con il manager
        var testResults = await managerToUse.ExecuteRawQueryAsync(testQuery);
        
        // Se validazione OK, salva il manager per ODBC
        if (IsOdbcConnection() && currentDatabaseManager == null && tempManager != null)
        {
            currentDatabaseManager = tempManager;
            tempManager = null; // Non distruggerlo nel finally
        }
    }
    finally
    {
        // Pulisci il manager temporaneo se non è stato salvato
        if (tempManager != null)
        {
            try { tempManager.Dispose(); } catch { /* Ignora errori di dispose */ }
        }
    }
}

Funzionalità:

  • Crea temporaneamente un OdbcDatabaseManager se non esiste
  • Usa questo manager per testare la query
  • Se la validazione ha successo, salva il manager in currentDatabaseManager per riutilizzarlo
  • Gestisce correttamente il dispose del manager temporaneo in caso di errore

2. DataCoupler.razor

Modificata: Sezione Pulsante Connessione

Prima:

@if (!string.IsNullOrEmpty(selectedDatabaseCredential))
{
    <div class="mb-3">
        <button class="btn btn-success btn-sm" @onclick="ConnectToDatabase">
            <i class="fas fa-plug"></i> Connetti e Scopri Schema
        </button>
    </div>
}

Dopo:

@if (!string.IsNullOrEmpty(selectedDatabaseCredential))
{
    <!-- Per ODBC: mostra messaggio esplicativo, niente discovery -->
    @if (IsOdbcConnection())
    {
        <div class="alert alert-info" role="alert">
            <i class="oi oi-info"></i> <strong>Connessione ODBC rilevata</strong><br>
            Per le connessioni ODBC, il discovery automatico delle tabelle non è disponibile.<br>
            Procedi direttamente con l'inserimento di una <strong>query SQL custom</strong> nella sezione sottostante.
        </div>
    }
    else
    {
        <!-- Per database standard: mostra pulsante di connessione -->
        <div class="mb-3">
            <button class="btn btn-success btn-sm" @onclick="ConnectToDatabase">
                <i class="fas fa-plug"></i> Connetti e Scopri Schema
            </button>
        </div>
    }
}

Funzionalità:

  • Per ODBC: mostra un messaggio informativo che spiega la situazione
  • Per altri database: mostra il pulsante di connessione standard
  • L'utente comprende immediatamente che deve usare query custom

Aggiunta: Sezione Query Custom per ODBC (sempre visibile)

<!-- Per ODBC: mostra direttamente la sezione Query Custom -->
@if (IsOdbcConnection())
{
    <!-- Sezione Query Custom per ODBC -->
    <div class="mb-3">
        <h6>Query SQL Custom:</h6>
        
        <div class="mb-2">
            <label class="form-label">Scrivi la tua query SELECT:</label>
            <textarea class="form-control" rows="6" 
                      placeholder="SELECT * FROM your_table WHERE condition..." 
                      @bind="customQuery" @bind:event="oninput"></textarea>
            <!-- Alert sicurezza -->
        </div>
        
        <div class="mb-2">
            <button class="btn btn-primary btn-sm me-2" @onclick="ValidateCustomQuery">
                <i class="fas fa-check-circle"></i> Valida Query
            </button>
            <!-- Altri pulsanti preview, ecc. -->
        </div>
    </div>
}

Funzionalità:

  • Sezione query custom sempre visibile quando si seleziona ODBC
  • Non richiede connessione preliminare
  • Include tutti i controlli per validazione, preview, ecc.

Modificata: Condizione Lista Tabelle

Prima:

@if (isDatabaseConnected)
{
    <!-- Lista tabelle e query custom switch -->
}

Dopo:

<!-- Lista Tabelle (solo per database NON ODBC) -->
@if (isDatabaseConnected && !IsOdbcConnection())
{
    <!-- Selezione modalità: Tabelle o Query Custom -->
    <!-- Lista tabelle -->
}

Funzionalità:

  • La sezione lista tabelle non viene mai mostrata per ODBC
  • Anche se isDatabaseConnected è true (non dovrebbe mai succedere per ODBC), la sezione resta nascosta

🔄 Flusso Utente ODBC

Prima dell'implementazione:

  1. Seleziona credenziale ODBC
  2. Clicca "Connetti e Scopri Schema"
  3. Errore: discovery tabelle fallisce
  4. User frustrato, deve capire come fare

Dopo l'implementazione:

  1. Seleziona credenziale ODBC
  2. Vede immediatamente messaggio informativo
  3. Vede la sezione query custom già pronta
  4. Scrive la query SQL
  5. Clicca "Valida Query" (crea automaticamente OdbcDatabaseManager)
  6. Vede preview dei dati
  7. Procede con il mapping

Nessun pulsante di connessione, nessun discovery, solo query diretta.

🎨 Esperienza Utente

Per Database Standard (SQL Server, MySQL, ecc.)

  • Mostra: Pulsante "Connetti e Scopri Schema"
  • Discovery: Automatico con lista tabelle
  • Query Custom: Opzionale, via switch

Per Database ODBC

  • Mostra: Messaggio informativo + textarea query
  • Discovery: Disabilitato completamente
  • Query Custom: Obbligatoria, sempre visibile

📊 Vantaggi dell'Implementazione

1. Affidabilità

  • Nessun rischio di errori nel discovery delle tabelle ODBC
  • L'utente ha il controllo completo della query SQL

2. Semplicità

  • Flusso chiaro: seleziona ODBC → scrivi query → valida → preview
  • Nessun passo intermedio confusionario

3. Performance

  • Nessun tentativo di discovery che può essere lento o fallire
  • Connessione ODBC creata solo quando serve (alla validazione)

4. Flessibilità

  • L'utente può scrivere qualsiasi query SELECT
  • Supporta JOIN, WHERE, GROUP BY, ecc.
  • Nessuna limitazione del discovery automatico

🔒 Sicurezza

Tutti i controlli di sicurezza esistenti restano attivi:

  • Solo query SELECT permesse
  • Query multiple (separate da ;) bloccate
  • Operazioni INSERT, UPDATE, DELETE, DROP bloccate
  • Query pulita da caratteri pericolosi

🧪 Test Manuali Suggeriti

Test 1: Selezione Credenziale ODBC

  1. Vai a DataCoupler
  2. Seleziona sorgente Database
  3. Seleziona una credenziale ODBC
  4. Verifica:
    • Nessun pulsante "Connetti e Scopri Schema"
    • Messaggio informativo visibile
    • Sezione query custom visibile
    • Textarea query pronta per input

Test 2: Validazione Query ODBC

  1. Seleziona credenziale ODBC
  2. Scrivi query: SELECT * FROM MyTable
  3. Clicca "Valida Query"
  4. Verifica:
    • Creazione automatica OdbcDatabaseManager
    • Query eseguita con successo
    • Colonne rilevate mostrate
    • Messaggio "Query valida - N colonne rilevate"

Test 3: Preview Dati ODBC

  1. Dopo validazione query (Test 2)
  2. Clicca "Anteprima Risultati"
  3. Verifica:
    • Preview tabella con 10 righe
    • Colonne corrette
    • Dati visualizzati correttamente

Test 4: Mapping e Trasferimento ODBC

  1. Dopo validazione e preview (Test 2-3)
  2. Procedi con configurazione destinazione
  3. Crea mapping campi
  4. Esegui trasferimento
  5. Verifica:
    • Trasferimento dati completato
    • Record copiati correttamente

Test 5: Confronto con Database Standard

  1. Seleziona credenziale SQL Server
  2. Verifica:
    • Pulsante "Connetti e Scopri Schema" visibile
    • Discovery tabelle funziona
    • Switch query custom disponibile
    • Nessun messaggio ODBC

📝 Note Tecniche

Manager ODBC Temporaneo

  • Creato on-demand durante la validazione query
  • Salvato in currentDatabaseManager se validazione OK
  • Riutilizzato per preview e trasferimento dati
  • Disposto correttamente in caso di errore

Compatibilità con Profili Esistenti

  • Profili ODBC con query custom salvate continuano a funzionare
  • Al caricamento profilo, se ODBC + query custom → valida automaticamente
  • Nessuna breaking change per profili esistenti

Dipendenze

  • OdbcDatabaseManager (già implementato)
  • DataConnectionFactory con supporto ODBC (già implementato)
  • DatabaseType.Odbc enum (già implementato)

🚀 Future Improvements

Possibili miglioramenti futuri (non implementati ora):

  1. Syntax Highlighting per query SQL nella textarea
  2. Query Templates predefiniti per ODBC comuni (SAP HANA, DB2, ecc.)
  3. Salvataggio Query Recenti per riutilizzo rapido
  4. Auto-complete Tabelle (se driver ODBC lo supporta)
  5. Explain Plan per query complesse

Versione: 2.2.0
Data Implementazione: 2 Febbraio 2026
Commit: 8a8ccec
Branch: development
Sviluppatore: Alessio Dalsanto