# 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()` ```csharp /// /// Verifica se la credenziale database selezionata è di tipo ODBC /// /// True se la credenziale è ODBC, altrimenti False 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()` ```csharp 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:** ```csharp 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:** ```razor @if (!string.IsNullOrEmpty(selectedDatabaseCredential)) {
} ``` **Dopo:** ```razor @if (!string.IsNullOrEmpty(selectedDatabaseCredential)) { @if (IsOdbcConnection()) { } else {
} } ``` **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) ```razor @if (IsOdbcConnection()) {
Query SQL Custom:
} ``` **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:** ```razor @if (isDatabaseConnected) { } ``` **Dopo:** ```razor @if (isDatabaseConnected && !IsOdbcConnection()) { } ``` **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