fix: Risolto errore "Invalid object name" nel trasferimento dati e pulizia codice
- Modificato GetAllRecordsAsync per utilizzare la stessa connection string del discovery schema - Aggiunto metodo CreateConnection per creare connessioni DB appropriate per tipo - Migliorata gestione nomi tabelle con schema (es. "dbo.OCRD") - Rimossi metodi obsoleti di creazione entità (UpdateEntityData, CreateNewEntity) - Eliminati riferimenti a variabili non dichiarate (newEntityData, isCreatingEntity) - Aggiunto logging debug per connection string e query SQL - Completata implementazione trasferimento dati da database a REST API Il trasferimento dati ora utilizza la stessa connessione per discovery e estrazione, risolvendo problemi di accesso alle tabelle durante l'operazione di upsert.
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
using CredentialManager.Models;
|
||||
using DataConnection.EF;
|
||||
using DataConnection.Interfaces;
|
||||
using DataConnection.REST.Interfaces;
|
||||
using DataConnection.REST.Implementations;
|
||||
using DataConnection.REST.Configuration;
|
||||
using DataConnection.CredentialManagement.Interfaces;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Data_Coupler.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory service per creare istanze di DatabaseManager e RestClient
|
||||
/// </summary>
|
||||
public interface IDataConnectionFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Crea un DatabaseManager per la credenziale specificata
|
||||
/// </summary>
|
||||
Task<IDatabaseManager> CreateDatabaseManagerAsync(string credentialName);
|
||||
|
||||
/// <summary>
|
||||
/// Crea un RestServiceClient per la credenziale specificata
|
||||
/// </summary>
|
||||
Task<IRestServiceClient> CreateRestServiceClientAsync(string credentialName);
|
||||
|
||||
/// <summary>
|
||||
/// Crea un RestMetadataDiscovery per la credenziale specificata
|
||||
/// </summary>
|
||||
Task<IRestMetadataDiscovery> CreateRestMetadataDiscoveryAsync(string credentialName);
|
||||
|
||||
/// <summary>
|
||||
/// Pulisce la cache del client REST per una credenziale specifica
|
||||
/// </summary>
|
||||
void ClearRestClientCache(string credentialName);
|
||||
/// <summary>
|
||||
/// Pulisce tutta la cache dei client REST
|
||||
/// </summary>
|
||||
void ClearAllRestClientCache();
|
||||
}
|
||||
|
||||
public class DataConnectionFactory : IDataConnectionFactory
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ILogger<DataConnectionFactory> _logger;
|
||||
private readonly IDataConnectionCredentialService _credentialService;
|
||||
|
||||
// Cache per mantenere le istanze dei client REST autenticati
|
||||
private readonly Dictionary<string, IRestServiceClient> _restClientCache = new();
|
||||
|
||||
public DataConnectionFactory(IServiceProvider serviceProvider, ILogger<DataConnectionFactory> logger, IDataConnectionCredentialService credentialService)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_logger = logger;
|
||||
_credentialService = credentialService;
|
||||
}public async Task<IDatabaseManager> CreateDatabaseManagerAsync(string credentialName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var credential = await _credentialService.GetDatabaseCredentialAsync(credentialName);
|
||||
if (credential == null)
|
||||
{
|
||||
throw new ArgumentException($"Credenziale database '{credentialName}' non trovata");
|
||||
}
|
||||
|
||||
var dbManagerOptions = await _credentialService.GetDbManagerOptionsAsync(credential.Name);
|
||||
return new EFCoreDatabaseManager(dbManagerOptions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Errore nella creazione del DatabaseManager per {CredentialName}", credentialName);
|
||||
throw;
|
||||
}
|
||||
} public async Task<IRestServiceClient> CreateRestServiceClientAsync(string credentialName)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Controlla se abbiamo già un client cached per questa credenziale
|
||||
if (_restClientCache.TryGetValue(credentialName, out var cachedClient))
|
||||
{
|
||||
_logger.LogInformation("Utilizzando client REST cached per {CredentialName}", credentialName);
|
||||
return cachedClient;
|
||||
}
|
||||
|
||||
var credential = await _credentialService.GetRestApiCredentialAsync(credentialName);
|
||||
if (credential == null)
|
||||
{
|
||||
throw new ArgumentException($"Credenziale REST API '{credentialName}' non trovata");
|
||||
} var options = new RestServiceOptions
|
||||
{
|
||||
BaseUrl = credential.BaseUrl,
|
||||
Username = credential.Username,
|
||||
Password = credential.Password,
|
||||
TimeoutSeconds = credential.TimeoutSeconds,
|
||||
IgnoreSslErrors = credential.IgnoreSslErrors
|
||||
}; // Mapping specifico per tipo di servizio
|
||||
switch (credential.ServiceType)
|
||||
{
|
||||
case RestServiceType.Salesforce:
|
||||
// Per Salesforce usiamo i campi specifici ClientId e ClientSecret
|
||||
options.ApiKey = credential.ClientId; // ClientId -> ApiKey
|
||||
options.AuthToken = credential.ClientSecret; // ClientSecret -> AuthToken
|
||||
_logger.LogInformation("Salesforce mapping - ClientId: {ClientId}, ClientSecret: {HasSecret}, Username: {Username}",
|
||||
credential.ClientId, !string.IsNullOrEmpty(credential.ClientSecret), credential.Username);
|
||||
break;
|
||||
case RestServiceType.SapB1ServiceLayer:
|
||||
// Per SAP B1 usiamo il CompanyDatabase come ApiKey
|
||||
options.ApiKey = credential.CompanyDatabase;
|
||||
options.AuthToken = credential.AuthToken;
|
||||
_logger.LogInformation("SAP B1 mapping - CompanyDB: {CompanyDB}, Username: {Username}",
|
||||
credential.CompanyDatabase, credential.Username);
|
||||
break;
|
||||
default:
|
||||
// Per servizi generici usiamo ApiKey e AuthToken direttamente
|
||||
options.ApiKey = credential.ApiKey;
|
||||
options.AuthToken = credential.AuthToken;
|
||||
_logger.LogInformation("Generic mapping - ApiKey: {ApiKey}, AuthToken: {HasToken}, Username: {Username}",
|
||||
credential.ApiKey, !string.IsNullOrEmpty(credential.AuthToken), credential.Username);
|
||||
break;
|
||||
}
|
||||
|
||||
var client = credential.ServiceType switch
|
||||
{
|
||||
RestServiceType.SapB1ServiceLayer => new SapB1ServiceClient(options),
|
||||
RestServiceType.Salesforce => CreateSalesforceClient(options),
|
||||
RestServiceType.Generic => CreateGenericRestClient(options),
|
||||
_ => throw new NotSupportedException($"Tipo di servizio REST non supportato: {credential.ServiceType}")
|
||||
};
|
||||
|
||||
// Salva il client nella cache
|
||||
_restClientCache[credentialName] = client;
|
||||
_logger.LogInformation("Client REST creato e cached per {CredentialName}", credentialName);
|
||||
|
||||
return client;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Errore nella creazione del RestServiceClient per {CredentialName}", credentialName);
|
||||
throw;
|
||||
}
|
||||
} public async Task<IRestMetadataDiscovery> CreateRestMetadataDiscoveryAsync(string credentialName)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Utilizza lo stesso client REST cached (che è già autenticato)
|
||||
var restClient = await CreateRestServiceClientAsync(credentialName);
|
||||
|
||||
// I service client già implementano IRestMetadataDiscovery
|
||||
if (restClient is IRestMetadataDiscovery metadataDiscovery)
|
||||
{
|
||||
_logger.LogInformation("Utilizzando lo stesso client REST per metadata discovery per {CredentialName}", credentialName);
|
||||
return metadataDiscovery;
|
||||
}
|
||||
|
||||
var credential = await _credentialService.GetRestApiCredentialAsync(credentialName);
|
||||
throw new NotSupportedException($"Il servizio REST {credential?.ServiceType} non supporta il metadata discovery");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Errore nella creazione del RestMetadataDiscovery per {CredentialName}", credentialName);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private IRestServiceClient CreateGenericRestClient(RestServiceOptions options)
|
||||
{
|
||||
var httpClientFactory = _serviceProvider.GetRequiredService<IHttpClientFactory>();
|
||||
var httpClient = httpClientFactory.CreateClient();
|
||||
return new BaseRestServiceClient(httpClient, options);
|
||||
}
|
||||
|
||||
private IRestServiceClient CreateSalesforceClient(RestServiceOptions options)
|
||||
{
|
||||
var httpClientFactory = _serviceProvider.GetRequiredService<IHttpClientFactory>();
|
||||
var httpClient = httpClientFactory.CreateClient();
|
||||
return new SalesforceServiceClient(httpClient, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pulisce la cache del client REST per una credenziale specifica
|
||||
/// </summary>
|
||||
public void ClearRestClientCache(string credentialName)
|
||||
{
|
||||
if (_restClientCache.Remove(credentialName))
|
||||
{
|
||||
_logger.LogInformation("Cache del client REST rimossa per {CredentialName}", credentialName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pulisce tutta la cache dei client REST
|
||||
/// </summary>
|
||||
public void ClearAllRestClientCache()
|
||||
{
|
||||
_restClientCache.Clear();
|
||||
_logger.LogInformation("Cache di tutti i client REST pulita");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user