6452d45b77
Implementata la possibilita' di usare Salesforce come fonte dati e un database relazionale come destinazione nel flusso di trasferimento dati. ## Modifiche principali ### Nuovi file partial class - Data_Coupler/Extensions/DataCoupler/SalesforceSourceMethod.cs - Stato e metodi per Salesforce come fonte (credenziali, connessione, discovery SObject) - ConnectToSalesforceSource(): autenticazione parallela + discovery summaries/details - SelectSalesforceSourceEntity(): selezione SObject e caricamento campi - GetAllRecordsFromSalesforceSource(): estrazione via ExtractAllEntitiesAsync con solo i campi mappati - Filtro/ricerca SObject in tempo reale - Data_Coupler/Extensions/DataCoupler/DatabaseDestinationMethod.cs - Stato e metodi per database come destinazione - ConnectToDestinationDatabase(): connessione e discovery tabelle - SelectDestinationTable(): caricamento schema tabella on-demand - IsDestinationDatabaseReady: proprieta' calcolata per validazione - Toggle UI tra destinazione REST e Database ### IDatabaseManager interface - Aggiunto UpsertRecordAsync(tableName, keyField, keyValue, record): - Esegue SELECT COUNT(*) per verificare esistenza record - UPDATE se esiste, INSERT se non esiste - Implementato in EFCoreDatabaseManager (parametri named @p0..@pN) - Implementato in OdbcDatabaseManager (parametri posizionali ?) ### DataCoupler.razor (UI) - Aggiunto 'Salesforce (REST API)' nel dropdown tipo fonte - Sezione UI Salesforce fonte: selettore credenziali, bottone connessione, lista SObject con ricerca - Toggle destinazione REST/Database nella card destra - Sezione UI Database destinazione: selettore credenziali, bottone connessione, lista tabelle con ricerca - Colonna destra mapping aggiornata: mostra colonne DB se destinazione e' database, proprieta' REST altrimenti - Colonna sinistra mapping: aggiunta sezione campi SObject Salesforce - isSourceReady aggiornato per includere fonte Salesforce - isDestinationReady aggiornato per includere destinazione database - Etichette mapping dinamiche in base ai tipi selezionati ### DataCoupler.razor.cs (logica) - LoadCredentials(): aggiunto caricamento credenziali Salesforce fonte - ResetSourceState(): aggiunto reset stato Salesforce fonte - ResetDestinationState(): aggiunto reset stato database destinazione - GetAllRecordsFromSource(): aggiunto branch Salesforce - StartDataTransfer(): routing verso StartDataTransferToDatabase() se dest=database - Aggiunto StartDataTransferToDatabase(): estrae record fonte, applica mapping e default values, chiama UpsertRecordAsync per ogni record - Rimosso codice duplicato in StartDataTransfer()
115 lines
4.4 KiB
C#
115 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq.Expressions;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace DataConnection.Interfaces;
|
|
|
|
/// <summary>
|
|
/// Interfaccia per la gestione di database preesistenti tramite EF Core
|
|
/// </summary>
|
|
public interface IDatabaseManager : IDisposable
|
|
{
|
|
/// <summary>
|
|
/// Verifica la connessione al database
|
|
/// </summary>
|
|
Task<bool> TestConnectionAsync();
|
|
|
|
/// <summary>
|
|
/// Ottiene entità dal database in base ai criteri specificati
|
|
/// </summary>
|
|
/// <typeparam name="T">Tipo di entità</typeparam>
|
|
/// <param name="filter">Espressione di filtro</param>
|
|
/// <param name="orderBy">Espressione di ordinamento</param>
|
|
/// <param name="includeProperties">Proprietà di navigazione da includere</param>
|
|
/// <param name="skip">Numero di elementi da saltare</param>
|
|
/// <param name="take">Numero di elementi da prendere</param>
|
|
Task<IEnumerable<T>> GetAsync<T>(
|
|
Expression<Func<T, bool>>? filter = null,
|
|
Func<IQueryable<T>, IOrderedQueryable<T>>? orderBy = null,
|
|
string includeProperties = "",
|
|
int? skip = null,
|
|
int? take = null) where T : class;
|
|
|
|
/// <summary>
|
|
/// Ottiene un'entità singola in base alla chiave primaria
|
|
/// </summary>
|
|
Task<T?> GetByIdAsync<T>(object id) where T : class;
|
|
|
|
/// <summary>
|
|
/// Esegue una query SQL raw
|
|
/// </summary>
|
|
Task<IEnumerable<T>> ExecuteQueryAsync<T>(string sql, params object[] parameters) where T : class;
|
|
|
|
/// <summary>
|
|
/// Esegue una query SQL raw e restituisce i risultati come dictionary
|
|
/// </summary>
|
|
Task<List<Dictionary<string, object>>> ExecuteRawQueryAsync(string sql, string databaseName = "", params object[] parameters);
|
|
|
|
/// <summary>
|
|
/// Esegue un comando SQL che non restituisce risultati
|
|
/// </summary>
|
|
Task<int> ExecuteCommandAsync(string sql, params object[] parameters);
|
|
|
|
/// <summary>
|
|
/// Ottiene l'elenco dei database disponibili sul server
|
|
/// </summary>
|
|
Task<List<string>> GetAvailableDatabasesAsync();
|
|
|
|
/// <summary>
|
|
/// Cambia il database corrente per la connessione
|
|
/// </summary>
|
|
Task ChangeDatabaseAsync(string databaseName);
|
|
/// <summary>
|
|
/// Ottiene i metadati delle tabelle nel database
|
|
/// </summary>
|
|
Task<IDictionary<string, IEnumerable<DbColumnInfo>>> GetDatabaseSchemaAsync();
|
|
|
|
/// <summary>
|
|
/// Ottiene solo la lista dei nomi delle tabelle disponibili (senza dettagli delle colonne)
|
|
/// </summary>
|
|
Task<IEnumerable<string>> GetTableNamesAsync();
|
|
|
|
/// <summary>
|
|
/// Ottiene i dettagli delle colonne per una specifica tabella
|
|
/// </summary>
|
|
/// <param name="tableName">Nome della tabella (con schema se necessario)</param>
|
|
Task<IEnumerable<DbColumnInfo>> GetTableSchemaAsync(string tableName);
|
|
|
|
/// <summary>
|
|
/// Ottiene tutti i record da una tabella specifica come dizionari chiave-valore
|
|
/// </summary>
|
|
Task<IEnumerable<Dictionary<string, object>>> GetAllRecordsAsync(string tableName);
|
|
|
|
/// <summary>
|
|
/// Ottiene il nome del campo Primary Key di una tabella specifica
|
|
/// </summary>
|
|
Task<string?> GetPrimaryKeyFieldAsync(string tableName);
|
|
|
|
/// <summary>
|
|
/// Esegue un upsert (INSERT o UPDATE) di un singolo record nella tabella specificata.
|
|
/// Se un record con lo stesso valore del campo chiave esiste già, viene aggiornato;
|
|
/// altrimenti viene inserito un nuovo record.
|
|
/// </summary>
|
|
/// <param name="tableName">Nome della tabella di destinazione</param>
|
|
/// <param name="keyField">Campo chiave per determinare se il record esiste</param>
|
|
/// <param name="keyValue">Valore del campo chiave del record</param>
|
|
/// <param name="record">Campi e valori da inserire/aggiornare</param>
|
|
/// <returns>True se l'operazione è riuscita, false altrimenti</returns>
|
|
Task<bool> UpsertRecordAsync(string tableName, string keyField, object? keyValue, Dictionary<string, object?> record);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Informazioni su una colonna del database
|
|
/// </summary>
|
|
public class DbColumnInfo
|
|
{
|
|
public string Name { get; set; } = string.Empty;
|
|
public string DataType { get; set; } = string.Empty;
|
|
public bool IsNullable { get; set; }
|
|
public bool IsPrimaryKey { get; set; }
|
|
public bool IsForeignKey { get; set; }
|
|
public string? ReferencedTable { get; set; }
|
|
public string? ReferencedColumn { get; set; }
|
|
}
|