[Feature] Supporto Visual FoxPro / dBase come sorgente dati (managed, sola lettura)
Aggiunge un connettore completamente managed per database Visual FoxPro e dBase, utilizzabile come sorgente dati in tutti i flussi dell'applicazione (discovery manuale, esecuzione schedulata, hash/change-detection, backup/restore). ## Motivazione Il provider OLE DB ufficiale (VFPOLEDB.1) è solo a 32-bit, deprecato e richiede installazione separata. Il connettore managed usa DbfDataReader 1.0.0 (MIT), legge direttamente i file .dbf/.fpt/.dbc a 64-bit senza dipendenze esterne e con streaming efficiente (tabelle da centinaia di MB con uso di memoria contenuto). ## Nuovi file - DataConnection/DB/FoxPro/FoxProConnectionInfo.cs Classe sealed con le informazioni di connessione risolte (cartella, percorso .dbc, encoding, flag IncludeDeleted). Proprietà di convenienza IsContainer e DisplayName. - DataConnection/DB/FoxPro/FoxProReader.cs Helper statico che registra CodePagesEncodingProvider, risolve la connection string (path diretto, stile OLE DB con Provider=vfpoledb, chiave=valore), verifica l'accesso al filesystem, legge il catalogo .dbc (il file .dbc è esso stesso un DBF; filtro su OBJECTTYPE='Table' + cross-check esistenza fisica .dbf), enumera le tabelle free, mappa i tipi VFP (Character, Memo, Numeric, Float, Double, Integer, Currency, Date, DateTime, Logical, General) in descrizioni leggibili, esegue streaming dei record via DbfDataReader, auto-rileva l'encoding dall'header DBF (language driver byte) con fallback a code page 1252, e analizza query SELECT [TOP n] * FROM tabella. - DataConnection/DB/FoxProDatabaseManager.cs Implementa IDatabaseManager. Lettura: TestConnectionAsync, GetTableNamesAsync, GetTableSchemaAsync, GetDatabaseSchemaAsync, GetAllRecordsAsync, ExecuteRawQueryAsync, GetPrimaryKeyFieldAsync (ritorna null, selezione manuale chiave), GetAvailableDatabasesAsync, ChangeDatabaseAsync (no-op per sorgenti file-based). Scrittura: tutti i metodi di modifica (Insert/Update/Delete/Upsert/BulkInsert/ ExecuteCommand/ExecuteNonQuery) lanciano NotSupportedException con messaggio esplicito. - DataConnection/DB/EF/SchemaProviders/FoxProSchemaProvider.cs Implementa IDatabaseSchemaProvider delegando a FoxProReader. Gestione errori per tabella in GetDatabaseSchemaAsync (una tabella non apribile non blocca la discovery). - FOXPRO_CONNECTION.md Guida utente: passo-passo per creare la credenziale, formato connection string, tabella tipi VFP supportati, note su sola lettura e limitazioni query, tabella risoluzione problemi (caratteri accentati, tabelle mancanti, ecc.). ## File modificati - DataConnection/DataConnection.csproj Aggiunto DbfDataReader 1.0.0 (porta transitivamente System.Text.Encoding.CodePages >= 10.0.3; rimossa dipendenza esplicita alla versione 9.0.3 che causava NU1605). - DataConnection/DB/Enums/DatabaseType.cs Aggiunto valore Foxpro in fondo all'enum (preserva valori già persistiti). - CredentialManager/Models/CredentialModels.cs Aggiunto DatabaseType.Foxpro all'enum e metodo BuildFoxproConnectionString che genera "Data Source=percorso[;CodePage=n][;IncludeDeleted=true]". - DataConnection/CredentialManagement/Models/CredentialExtensions.cs Mappatura bidirezionale Foxpro tra enum CredentialManager e DataConnection. - DataConnection/CredentialManagement/Services/DataConnectionCredentialService.cs Aggiunto TestFoxproConnection: verifica percorso accessibile, legge nomi tabelle, restituisce messaggio con conteggio tabelle, encoding rilevato e nota sola lettura. - DataConnection/DB/EF/DatabaseSchemaProviderFactory.cs Caso Foxpro => new FoxProSchemaProvider(). - Data_Coupler/Services/DataConnectionFactory.cs Branch Foxpro => new FoxProDatabaseManager(connectionString). - Data_Coupler/Extensions/DataCoupler/DatabaseMethod.cs Aggiunto IsFoxproConnection() e caso Foxpro in CreateLimitedQuery (SELECT TOP n * FROM (query) AS subquery). - CredentialManager/Integration/DataConnectionHelper.cs ValidateDatabaseCredential: introdotto flag isFileBased (Sqlite || Foxpro) per esonerare host/utente/password/porta; messaggio di errore specifico per il campo percorso FoxPro. - Data_Coupler/Pages/CredentialManagement.razor Aggiunta opzione "Visual FoxPro (.dbc / .dbf)" nel selettore tipo database. Sezione di configurazione dedicata: banner sola lettura, campo percorso con esempi (.dbc e cartella), dropdown code page (Auto/1252/1250/1251/850/437/65001), checkbox record cancellati, pannello tipi supportati, anteprima connection string. Fix validazione form test-connessione: branch Foxpro che verifica solo DatabaseName (non Host/Username/Password), eliminando il falso errore "Il campo Host è obbligatorio". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -58,7 +58,8 @@ public enum DatabaseType
|
||||
DB2,
|
||||
SapHana,
|
||||
Odbc,
|
||||
OleDb
|
||||
OleDb,
|
||||
Foxpro
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -200,6 +201,7 @@ public static class ConnectionStringBuilder
|
||||
DatabaseType.SapHana => BuildSapHanaConnectionString(credential),
|
||||
DatabaseType.Odbc => BuildOdbcConnectionString(credential),
|
||||
DatabaseType.OleDb => BuildOleDbConnectionString(credential),
|
||||
DatabaseType.Foxpro => BuildFoxproConnectionString(credential),
|
||||
_ => throw new NotSupportedException($"Database type {credential.DatabaseType} not supported")
|
||||
};
|
||||
} private static string BuildSqlServerConnectionString(DatabaseCredential credential)
|
||||
@@ -474,6 +476,37 @@ public static class ConnectionStringBuilder
|
||||
return string.Join(";", builder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Costruisce la "connection string" per una sorgente Visual FoxPro / dBase.
|
||||
/// FoxPro non usa un vero connection string: serve solo il percorso (file .dbc o cartella di .dbf),
|
||||
/// salvato in <see cref="DatabaseCredential.DatabaseName"/>. Le opzioni encoding/record cancellati
|
||||
/// vengono aggiunte come chiavi CodePage/IncludeDeleted, interpretate da FoxProReader.
|
||||
/// </summary>
|
||||
private static string BuildFoxproConnectionString(DatabaseCredential credential)
|
||||
{
|
||||
// Una connection string esplicita (es. incollata dall'utente) ha la precedenza.
|
||||
if (!string.IsNullOrEmpty(credential.ConnectionString))
|
||||
return credential.ConnectionString;
|
||||
|
||||
var path = !string.IsNullOrEmpty(credential.DatabaseName)
|
||||
? credential.DatabaseName
|
||||
: credential.Host;
|
||||
|
||||
var builder = new List<string> { $"Data Source={path}" };
|
||||
|
||||
if (credential.AdditionalParameters != null)
|
||||
{
|
||||
if (credential.AdditionalParameters.TryGetValue("Encoding", out var enc) && !string.IsNullOrWhiteSpace(enc))
|
||||
builder.Add($"CodePage={enc}");
|
||||
|
||||
if (credential.AdditionalParameters.TryGetValue("IncludeDeleted", out var del) &&
|
||||
del.Equals("true", StringComparison.OrdinalIgnoreCase))
|
||||
builder.Add("IncludeDeleted=true");
|
||||
}
|
||||
|
||||
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