- Implementata funzionalità completa External ID Relationships nell'interfaccia di mapping
- Corretto bug double-mapping: i campi sorgente usati per External ID non vengono più inclusi nei mapping normali
- Risolto errore MALFORMED_ID causato dall'invio duplicato di campi come proprietà dirette e nested objects
- Implementata logica corretta per relationship names: oggetti standard usano il nome diretto, custom objects usano suffisso __r
- Aggiunta UI a 3 colonne (Object, External ID Field, Source Field) per configurazione External ID Relationships
- Migrazione database per supporto External ID Relationships nei profili
- Aggiornato ProfileSaver.razor.cs per salvare/caricare External ID Relationships
- Aggiornato ScheduledProfileExecutionService.cs per gestire External ID nelle esecuzioni schedulate
- Formato JSON output corretto: { 'Account': { 'CardCode__c': 'V50000' } }
Documentazione: EXTERNAL_ID_RELATIONSHIPS_IMPLEMENTATION.md
11 KiB
Fix Connessione SQL Server con Localhost
Data: 15 Febbraio 2026
Versione: 2.1+
📋 Problema Risolto
Il sistema non riusciva a connettersi correttamente a SQL Server quando si utilizzava "localhost" come host, specialmente per:
- Named Instances (es.
localhost\SQLEXPRESS) - LocalDB (es.
(localdb)\MSSQLLocalDB) - Windows Authentication
🔧 Modifiche Implementate
1. ConnectionStringBuilder - Gestione Intelligente del Server
File: CredentialManager/Models/CredentialModels.cs
Miglioramenti:
a) Named Instances
- Se l'host contiene
\(backslash), la porta viene omessa automaticamente - Esempi supportati:
localhost\SQLEXPRESS.\SQLEXPRESSSERVERNAME\INSTANCE
b) LocalDB
- Se l'host inizia con
(localdb), la porta viene omessa - Esempi supportati:
(localdb)\MSSQLLocalDB(localdb)\v11.0(localdb)\ProjectsV13
c) Localhost con Named Pipes
- Per
localhost,.o127.0.0.1con porta 1433 (default), la porta viene omessa - Questo permette a SQL Server di usare Named Pipes invece di TCP/IP per connessioni locali più veloci
d) Windows Authentication
- Se username è vuoto,
IntegratedoWindows, usa Windows Authentication - Non richiede password quando si usa Windows Authentication
- Connection string include
Integrated Security=True
Codice Modificato:
private static string BuildSqlServerConnectionString(DatabaseCredential credential)
{
var builder = new List<string>();
// Gestione speciale per SQL Server locale e named instances
bool hasInstanceName = credential.Host.Contains('\\') ||
credential.Host.StartsWith("(localdb)", StringComparison.OrdinalIgnoreCase);
if (hasInstanceName)
{
// Per named instances e LocalDB, non includere la porta
builder.Add($"Server={credential.Host}");
}
else
{
// Per localhost con porta default, ometti la porta per usare Named Pipes
if ((credential.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase) ||
credential.Host == "." ||
credential.Host == "127.0.0.1") && credential.Port == 1433)
{
builder.Add($"Server={credential.Host}");
}
else
{
// Per altri casi, usa host,porta
builder.Add($"Server={credential.Host},{credential.Port}");
}
}
// Windows Authentication vs SQL Authentication
if (string.IsNullOrWhiteSpace(credential.Username) ||
credential.Username.Equals("Integrated", StringComparison.OrdinalIgnoreCase) ||
credential.Username.Equals("Windows", StringComparison.OrdinalIgnoreCase))
{
builder.Add("Integrated Security=True");
}
else
{
builder.Add($"User Id={credential.Username}");
builder.Add($"Password={credential.Password}");
}
builder.Add($"Connection Timeout={credential.CommandTimeout}");
if (!string.IsNullOrEmpty(credential.DatabaseName))
builder.Add($"Database={credential.DatabaseName}");
if (credential.IgnoreSslErrors)
builder.Add("TrustServerCertificate=True");
return string.Join(";", builder);
}
2. UI - Guida Contestuale per SQL Server
File: Data_Coupler/Pages/CredentialManagement.razor
Aggiunte:
a) Help Text per Host/Server
- Mostra esempi specifici per SQL Server locale:
- Named Instance:
localhost\SQLEXPRESSo.\SQLEXPRESS - LocalDB:
(localdb)\MSSQLLocalDB - Default:
localhosto.(usa porta 1433)
- Named Instance:
b) Nota sulla Porta
- Indica che la porta viene ignorata per named instances e LocalDB
c) Guida Windows Authentication
- Nel campo Username: placeholder "o scrivi 'Integrated' per Windows Auth"
- Help text: "Per Windows Authentication, scrivi Integrated o lascia vuoto"
- Nel campo Password: "Non richiesta per Windows Authentication"
Codice Aggiunto:
@if (currentDatabaseCredential.DatabaseType == DatabaseType.SqlServer)
{
<div class="form-text">
<strong>SQL Server locale:</strong><br/>
• Named Instance: <code>localhost\SQLEXPRESS</code> o <code>.\SQLEXPRESS</code><br/>
• LocalDB: <code>(localdb)\MSSQLLocalDB</code><br/>
• Default: <code>localhost</code> o <code>.</code> (usa porta 1433)
</div>
}
3. Validazione Aggiornata
File: Data_Coupler/Pages/CredentialManagement.razor
Miglioramenti:
a) Validazione Credenziali
- Permette username/password vuoti per SQL Server con Windows Authentication
- Riconosce "Integrated" e "Windows" come segnali per Windows Authentication
- Validazione più specifica con messaggi di errore appropriati
Codice Modificato:
// Per SQL Server, permetti Windows Authentication
bool isSqlServerWithWindowsAuth = currentDatabaseCredential.DatabaseType == DatabaseType.SqlServer &&
(string.IsNullOrWhiteSpace(currentDatabaseCredential.Username) ||
currentDatabaseCredential.Username.Equals("Integrated", StringComparison.OrdinalIgnoreCase) ||
currentDatabaseCredential.Username.Equals("Windows", StringComparison.OrdinalIgnoreCase));
if (!isSqlServerWithWindowsAuth)
{
// Per database che non usano Windows Authentication, richiedi username e password
if (string.IsNullOrEmpty(currentDatabaseCredential.Username) ||
string.IsNullOrEmpty(currentDatabaseCredential.Password))
{
await JSRuntime.InvokeVoidAsync("alert",
"Username e Password sono obbligatori. Per SQL Server con Windows Authentication, inserisci 'Integrated' come username.");
return;
}
}
📚 Guida Utilizzo
Scenario 1: SQL Server Express Locale
Configurazione Credenziale:
- Host:
localhost\SQLEXPRESSo.\SQLEXPRESS - Porta: 1433 (ignorata)
- Database: Nome del database (es.
MyDatabase) - Username:
Integratedo lascia vuoto - Password: Lascia vuoto
Connection String Generata:
Server=localhost\SQLEXPRESS;Integrated Security=True;Connection Timeout=30;Database=MyDatabase;TrustServerCertificate=True
Scenario 2: SQL Server LocalDB
Configurazione Credenziale:
- Host:
(localdb)\MSSQLLocalDB - Porta: 1433 (ignorata)
- Database: Nome del database (es.
TestDB) - Username:
Integratedo lascia vuoto - Password: Lascia vuoto
Connection String Generata:
Server=(localdb)\MSSQLLocalDB;Integrated Security=True;Connection Timeout=30;Database=TestDB
Scenario 3: SQL Server Locale con SQL Authentication
Configurazione Credenziale:
- Host:
localhost - Porta: 1433
- Database: Nome del database (es.
Production) - Username:
sa(o un altro utente SQL) - Password: Password dell'utente
Connection String Generata:
Server=localhost;User Id=sa;Password=***;Connection Timeout=30;Database=Production;TrustServerCertificate=True
Scenario 4: SQL Server Remoto
Configurazione Credenziale:
- Host:
sql.example.com - Porta: 1433 (o porta custom, es. 14330)
- Database: Nome del database
- Username: Utente SQL
- Password: Password
Connection String Generata:
Server=sql.example.com,1433;User Id=username;Password=***;Connection Timeout=30;Database=DBName;TrustServerCertificate=True
Scenario 5: SQL Server con Instance Name Remoto
Configurazione Credenziale:
- Host:
server.domain.com\PRODUCTION - Porta: 1433 (ignorata)
- Database: Nome del database
- Username: Utente SQL
- Password: Password
Connection String Generata:
Server=server.domain.com\PRODUCTION;User Id=username;Password=***;Connection Timeout=30;Database=DBName;TrustServerCertificate=True
🔍 Troubleshooting
Problema: "A network-related or instance-specific error"
Possibili Cause:
-
SQL Server Browser non in esecuzione (per named instances)
- Soluzione: Avvia il servizio "SQL Server Browser" da services.msc
-
TCP/IP non abilitato
- Soluzione: SQL Server Configuration Manager → Protocols → Enable TCP/IP
-
Named Instance non specificata
- Soluzione: Usa
localhost\SQLEXPRESSinvece di sololocalhost
- Soluzione: Usa
-
Firewall blocca la porta
- Soluzione: Aggiungi eccezione firewall per SQL Server
Problema: "Login failed for user"
Possibili Cause:
-
Windows Authentication richiesta ma SQL Auth specificata
- Soluzione: Usa username
Integratedo lascialo vuoto
- Soluzione: Usa username
-
SQL Authentication non abilitata
- Soluzione: SQL Server Management Studio → Proprietà Server → Security → SQL Server and Windows Authentication mode
-
Password errata
- Soluzione: Verifica la password
Problema: "Cannot open database"
Possibili Cause:
-
Database non esiste
- Soluzione: Verifica il nome del database o lascia il campo vuoto per connetterti solo al server
-
Permessi insufficienti
- Soluzione: Verifica che l'utente abbia accesso al database
✅ Test di Connessione
Dopo aver configurato la credenziale, usa il pulsante "Testa Connessione" per verificare:
- ✅ Connection string corretta
- ✅ SQL Server raggiungibile
- ✅ Autenticazione riuscita
- ✅ Database accessibile (se specificato)
Il test mostra:
- Versione SQL Server
- Host e porta usati
- Database connesso
- Timeout configurato
📝 Note Tecniche
Differenze TCP/IP vs Named Pipes
Named Pipes (preferito per localhost):
- Più veloce per connessioni locali
- Non richiede SQL Server Browser
- Usa IPC invece di network stack
- Sintassi:
Server=localhostoServer=.
TCP/IP (richiesto per remote):
- Richiesto per connessioni remote
- Richiede porta specifica
- Richiede SQL Server Browser per named instances
- Sintassi:
Server=hostname,port
Windows Authentication vs SQL Authentication
Windows Authentication:
- ✅ Più sicuro (usa credenziali Windows)
- ✅ No password nel codice
- ✅ Single Sign-On
- ❌ Richiede domain trust per remote
SQL Authentication:
- ✅ Funziona sempre (anche cross-domain)
- ✅ Credenziali specifiche per SQL Server
- ❌ Password nel connection string
- ❌ Deve essere abilitato in SQL Server
🔄 Retrocompatibilità
Le modifiche sono completamente retrocompatibili:
- ✅ Connection string esistenti continuano a funzionare
- ✅ Credenziali già salvate non richiedono modifiche
- ✅ Comportamento default invariato per server remoti
- ✅ Nessuna migrazione database richiesta
📊 Impatto Performance
Miglioramenti:
- 🚀 Named Pipes più veloce di TCP/IP per localhost
- 🚀 Riduzione overhead network stack
- 🚀 Connection pooling più efficiente
Nessun Impatto Negativo:
- ✅ Server remoti usano sempre TCP/IP (comportamento corretto)
- ✅ Connection string ottimizzate per scenario specifico
Sviluppatore: Alessio Dalsanto
Issue: Connessione localhost SQL Server
Status: ✅ Risolto