[Feature] Implementazione completa supporto ODBC
- Aggiunta persistenza campi ODBC (OdbcDsnName, OdbcMode) in CredentialEntity - Creata migration EF Core per nuovi campi database - Aggiornato mapping credenziali per caricare/salvare dati ODBC - Creato OdbcDatabaseManager dedicato (bypass EF Core che non supporta ODBC) - Aggiornato DataConnectionFactory per usare OdbcDatabaseManager con connessioni ODBC - Fix auto-load DSN: sostituito @onchange con @bind-Value:after in dropdown tipo database - Fix test connessione SAP HANA: rimossa query SELECT 1 che causava errori sintassi - Implementati tutti i metodi IDatabaseManager in OdbcDatabaseManager - Supporto completo per discovery schema, tabelle e query ODBC Risolve problema DbContext non configurato per ODBC e abilita connessioni ODBC complete.
This commit is contained in:
@@ -61,6 +61,13 @@ public class CredentialEntity
|
||||
[MaxLength(2000)]
|
||||
public string? AdditionalParameters { get; set; } // JSON per parametri aggiuntivi
|
||||
|
||||
// ODBC specific fields
|
||||
[MaxLength(100)]
|
||||
public string? OdbcDsnName { get; set; } // Nome del DSN ODBC configurato
|
||||
|
||||
[MaxLength(20)]
|
||||
public string? OdbcMode { get; set; } // Dsn o Custom (OdbcConnectionMode enum)
|
||||
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
@@ -33,7 +33,24 @@ public enum DatabaseType
|
||||
Oracle,
|
||||
Sqlite,
|
||||
DB2,
|
||||
SapHana
|
||||
SapHana,
|
||||
Odbc
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modalità di connessione ODBC
|
||||
/// </summary>
|
||||
public enum OdbcConnectionMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Utilizzo di un DSN (Data Source Name) configurato
|
||||
/// </summary>
|
||||
Dsn,
|
||||
|
||||
/// <summary>
|
||||
/// Costruzione manuale della connection string
|
||||
/// </summary>
|
||||
Custom
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -52,6 +69,10 @@ public class DatabaseCredential
|
||||
public int CommandTimeout { get; set; } = 30;
|
||||
public bool IgnoreSslErrors { get; set; } = false;
|
||||
public Dictionary<string, string>? AdditionalParameters { get; set; }
|
||||
|
||||
// ODBC specific properties
|
||||
public string? OdbcDsnName { get; set; } // Nome del DSN ODBC (se utilizzato)
|
||||
public OdbcConnectionMode OdbcMode { get; set; } = OdbcConnectionMode.Dsn; // Modalità ODBC (DSN o Custom)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -148,6 +169,7 @@ public static class ConnectionStringBuilder
|
||||
DatabaseType.Sqlite => BuildSqliteConnectionString(credential),
|
||||
DatabaseType.DB2 => BuildDb2ConnectionString(credential),
|
||||
DatabaseType.SapHana => BuildSapHanaConnectionString(credential),
|
||||
DatabaseType.Odbc => BuildOdbcConnectionString(credential),
|
||||
_ => throw new NotSupportedException($"Database type {credential.DatabaseType} not supported")
|
||||
};
|
||||
} private static string BuildSqlServerConnectionString(DatabaseCredential credential)
|
||||
@@ -275,6 +297,74 @@ public static class ConnectionStringBuilder
|
||||
return string.Join(";", builder);
|
||||
}
|
||||
|
||||
private static string BuildOdbcConnectionString(DatabaseCredential credential)
|
||||
{
|
||||
// Se è già presente una connection string personalizzata, utilizzala
|
||||
if (!string.IsNullOrEmpty(credential.ConnectionString))
|
||||
return credential.ConnectionString;
|
||||
|
||||
var builder = new List<string>();
|
||||
|
||||
// Modalità DSN: usa il DSN configurato
|
||||
if (credential.OdbcMode == OdbcConnectionMode.Dsn && !string.IsNullOrEmpty(credential.OdbcDsnName))
|
||||
{
|
||||
builder.Add($"DSN={credential.OdbcDsnName}");
|
||||
|
||||
// Aggiungi credenziali se fornite
|
||||
if (!string.IsNullOrEmpty(credential.Username))
|
||||
builder.Add($"UID={credential.Username}");
|
||||
|
||||
if (!string.IsNullOrEmpty(credential.Password))
|
||||
builder.Add($"PWD={credential.Password}");
|
||||
}
|
||||
// Modalità Custom: costruisci manualmente la connection string
|
||||
else
|
||||
{
|
||||
// Driver (se specificato nei parametri aggiuntivi)
|
||||
if (credential.AdditionalParameters?.ContainsKey("Driver") == true)
|
||||
{
|
||||
builder.Add($"Driver={{{credential.AdditionalParameters["Driver"]}}}");
|
||||
}
|
||||
|
||||
// Server/Host
|
||||
if (!string.IsNullOrEmpty(credential.Host))
|
||||
{
|
||||
builder.Add($"Server={credential.Host}");
|
||||
|
||||
// Porta (se diversa da 0)
|
||||
if (credential.Port > 0)
|
||||
builder.Add($"Port={credential.Port}");
|
||||
}
|
||||
|
||||
// Database
|
||||
if (!string.IsNullOrEmpty(credential.DatabaseName))
|
||||
builder.Add($"Database={credential.DatabaseName}");
|
||||
|
||||
// Credenziali
|
||||
if (!string.IsNullOrEmpty(credential.Username))
|
||||
builder.Add($"UID={credential.Username}");
|
||||
|
||||
if (!string.IsNullOrEmpty(credential.Password))
|
||||
builder.Add($"PWD={credential.Password}");
|
||||
}
|
||||
|
||||
// Timeout
|
||||
if (credential.CommandTimeout > 0)
|
||||
builder.Add($"Connection Timeout={credential.CommandTimeout}");
|
||||
|
||||
// Parametri aggiuntivi (escludendo Driver se già aggiunto)
|
||||
if (credential.AdditionalParameters != null)
|
||||
{
|
||||
foreach (var param in credential.AdditionalParameters)
|
||||
{
|
||||
if (param.Key != "Driver") // Driver già gestito sopra
|
||||
builder.Add($"{param.Key}={param.Value}");
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join(";", builder);
|
||||
}
|
||||
|
||||
private static void AddAdditionalParameters(List<string> builder, Dictionary<string, string>? additionalParams)
|
||||
{
|
||||
if (additionalParams != null)
|
||||
|
||||
Reference in New Issue
Block a user