Files
Data-Coupler/DataConnection/CredentialManagement/Models/CredentialExtensions.cs
T
Alessio e70abcdcb1 [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>
2026-06-06 19:34:21 +02:00

108 lines
4.8 KiB
C#

using CredentialManager.Models;
namespace DataConnection.CredentialManagement.Models;
/// <summary>
/// Extension methods per convertire le credenziali CredentialManager in oggetti DataConnection
/// </summary>
public static class CredentialExtensions
{
/// <summary>
/// Converte il tipo di database da CredentialManager.Models.DatabaseType a DataConnection.Enums.DatabaseType
/// </summary>
public static DataConnection.Enums.DatabaseType ToDataConnectionDatabaseType(this CredentialManager.Models.DatabaseType credentialDbType)
{
return credentialDbType switch
{
CredentialManager.Models.DatabaseType.SqlServer => DataConnection.Enums.DatabaseType.SqlServer,
CredentialManager.Models.DatabaseType.MySql => DataConnection.Enums.DatabaseType.MySql,
CredentialManager.Models.DatabaseType.PostgreSql => DataConnection.Enums.DatabaseType.PostgreSql,
CredentialManager.Models.DatabaseType.Oracle => DataConnection.Enums.DatabaseType.Oracle,
CredentialManager.Models.DatabaseType.Sqlite => DataConnection.Enums.DatabaseType.Sqlite,
CredentialManager.Models.DatabaseType.DB2 => DataConnection.Enums.DatabaseType.DB2,
CredentialManager.Models.DatabaseType.SapHana => DataConnection.Enums.DatabaseType.SapHana,
CredentialManager.Models.DatabaseType.Odbc => DataConnection.Enums.DatabaseType.Odbc,
CredentialManager.Models.DatabaseType.OleDb => DataConnection.Enums.DatabaseType.OleDb,
CredentialManager.Models.DatabaseType.Foxpro => DataConnection.Enums.DatabaseType.Foxpro,
_ => throw new NotSupportedException($"Database type {credentialDbType} not supported")
};
}
/// <summary>
/// Converte il tipo di database da DataConnection.Enums.DatabaseType a CredentialManager.Models.DatabaseType
/// </summary>
public static CredentialManager.Models.DatabaseType ToCredentialDatabaseType(this DataConnection.Enums.DatabaseType dataConnectionDbType)
{
return dataConnectionDbType switch
{
DataConnection.Enums.DatabaseType.SqlServer => CredentialManager.Models.DatabaseType.SqlServer,
DataConnection.Enums.DatabaseType.MySql => CredentialManager.Models.DatabaseType.MySql,
DataConnection.Enums.DatabaseType.PostgreSql => CredentialManager.Models.DatabaseType.PostgreSql,
DataConnection.Enums.DatabaseType.Oracle => CredentialManager.Models.DatabaseType.Oracle,
DataConnection.Enums.DatabaseType.Sqlite => CredentialManager.Models.DatabaseType.Sqlite,
DataConnection.Enums.DatabaseType.DB2 => CredentialManager.Models.DatabaseType.DB2,
DataConnection.Enums.DatabaseType.SapHana => CredentialManager.Models.DatabaseType.SapHana,
DataConnection.Enums.DatabaseType.Odbc => CredentialManager.Models.DatabaseType.Odbc,
DataConnection.Enums.DatabaseType.OleDb => CredentialManager.Models.DatabaseType.OleDb,
DataConnection.Enums.DatabaseType.Foxpro => CredentialManager.Models.DatabaseType.Foxpro,
_ => throw new NotSupportedException($"Database type {dataConnectionDbType} not supported")
};
}
/// <summary>
/// Crea una DatabaseCredential da parametri di connessione
/// </summary>
public static DatabaseCredential CreateDatabaseCredential(
string name,
DataConnection.Enums.DatabaseType databaseType,
string host,
int port,
string databaseName,
string username,
string password,
int commandTimeout = 30,
bool ignoreSslErrors = false)
{
return new DatabaseCredential
{
Name = name,
DatabaseType = databaseType.ToCredentialDatabaseType(),
Host = host,
Port = port,
DatabaseName = databaseName,
Username = username,
Password = password,
CommandTimeout = commandTimeout,
IgnoreSslErrors = ignoreSslErrors
};
}
/// <summary>
/// Crea una RestApiCredential da parametri di connessione
/// </summary>
public static RestApiCredential CreateRestApiCredential(
string name,
string baseUrl,
string? apiKey = null,
string? username = null,
string? password = null,
string? authToken = null,
int timeoutSeconds = 100,
bool ignoreSslErrors = false,
Dictionary<string, string>? headers = null)
{
return new RestApiCredential
{
Name = name,
BaseUrl = baseUrl,
ApiKey = apiKey,
Username = username,
Password = password,
AuthToken = authToken,
TimeoutSeconds = timeoutSeconds,
IgnoreSslErrors = ignoreSslErrors,
Headers = headers
};
}
}