Aggiornata la documentazione per gli agents
This commit is contained in:
@@ -0,0 +1,921 @@
|
||||
# Data-Coupler: Sistema di Integrazione Dati Multi-Platform
|
||||
|
||||
## 📋 Project Overview
|
||||
|
||||
**Data-Coupler** è una soluzione enterprise di integrazione dati sviluppata in .NET 9.0 con architettura Blazor Server. Il sistema facilita il trasferimento e la sincronizzazione di dati tra diverse tipologie di sorgenti: database relazionali, REST API, file Excel/CSV.
|
||||
|
||||
### 🎯 Obiettivi del Progetto
|
||||
- **Unificazione Data Sources**: Connessione trasparente a database eterogenei e API REST
|
||||
- **Trasferimenti Sicuri**: Gestione crittografata delle credenziali cross-platform
|
||||
- **Automazione**: Sistema di scheduling per operazioni periodiche
|
||||
- **Mappatura Intelligente**: Sistema avanzato di mapping campi tra sorgenti diverse
|
||||
- **Gestione Associazioni**: Tracking delle chiavi per evitare duplicati e gestire relazioni
|
||||
|
||||
### 🏗️ Architettura del Sistema
|
||||
|
||||
#### Struttura Modulare
|
||||
```
|
||||
Data-Coupler/
|
||||
├── Data_Coupler/ # 🎯 Applicazione principale Blazor Server
|
||||
├── DataConnection/ # 🔌 Libreria core per connessioni dati
|
||||
├── CredentialManager/ # 🔐 Gestione sicura credenziali
|
||||
├── Components/ # 🧩 Componenti UI riutilizzabili
|
||||
└── DatabaseUpdater/ # 🔧 Utility per manutenzione database
|
||||
```
|
||||
|
||||
#### Stack Tecnologico
|
||||
- **.NET 9.0**: Framework principale
|
||||
- **Blazor Server**: Framework UI reattivo
|
||||
- **Entity Framework Core**: ORM per accesso dati
|
||||
- **SQLite**: Database embedded per configurazioni
|
||||
- **Bootstrap 5**: Framework CSS responsive
|
||||
|
||||
#### Database Supportati
|
||||
- SQL Server, MySQL, PostgreSQL, Oracle, SQLite, IBM DB2, SAP HANA
|
||||
|
||||
#### REST API Supportate
|
||||
- Generic REST APIs, Salesforce, SAP Business One Service Layer
|
||||
|
||||
## 🔨 Build and Test Commands
|
||||
|
||||
### Prerequisiti
|
||||
- .NET 9.0 SDK
|
||||
- Git per clone del repository
|
||||
- Editor: Visual Studio 2022, VS Code, o Rider
|
||||
|
||||
### Setup Ambiente di Sviluppo
|
||||
```bash
|
||||
# Clone del repository
|
||||
git clone https://github.com/AlessioDalsi/Data-Coupler.git
|
||||
cd Data-Coupler
|
||||
|
||||
# Restore dei pacchetti NuGet
|
||||
dotnet restore Data_Coupler.sln
|
||||
```
|
||||
|
||||
### Build Commands
|
||||
|
||||
#### Build Development
|
||||
```bash
|
||||
# Build completo della soluzione
|
||||
dotnet build Data_Coupler.sln
|
||||
|
||||
# Build singolo progetto
|
||||
dotnet build Data_Coupler/Data_Coupler.csproj
|
||||
dotnet build DataConnection/DataConnection.csproj
|
||||
dotnet build CredentialManager/CredentialManager.csproj
|
||||
```
|
||||
|
||||
#### Build Production
|
||||
```bash
|
||||
# Build release
|
||||
dotnet build Data_Coupler.sln --configuration Release
|
||||
|
||||
# Publish per deployment
|
||||
dotnet publish Data_Coupler/Data_Coupler.csproj \
|
||||
--configuration Release \
|
||||
--output ./publish \
|
||||
--self-contained true \
|
||||
--runtime win-x64
|
||||
```
|
||||
|
||||
#### Build per Diverse Piattaforme
|
||||
```bash
|
||||
# Windows x64
|
||||
dotnet publish --runtime win-x64 --configuration Release
|
||||
|
||||
# Linux x64
|
||||
dotnet publish --runtime linux-x64 --configuration Release
|
||||
|
||||
# macOS x64
|
||||
dotnet publish --runtime osx-x64 --configuration Release
|
||||
|
||||
# macOS ARM64 (Apple Silicon)
|
||||
dotnet publish --runtime osx-arm64 --configuration Release
|
||||
```
|
||||
|
||||
### Run Commands
|
||||
|
||||
#### Sviluppo Locale
|
||||
```bash
|
||||
# Avvio applicazione principale
|
||||
dotnet run --project Data_Coupler/Data_Coupler.csproj
|
||||
|
||||
# Avvio con hot reload
|
||||
dotnet watch run --project Data_Coupler/Data_Coupler.csproj
|
||||
|
||||
# Avvio su porta specifica
|
||||
dotnet run --project Data_Coupler/Data_Coupler.csproj --urls "http://localhost:8080"
|
||||
```
|
||||
|
||||
#### Utility e Manutenzione
|
||||
```bash
|
||||
# Aggiornamento database
|
||||
dotnet run --project DatabaseUpdater/DatabaseUpdater.csproj
|
||||
|
||||
# Creazione migrazione Entity Framework
|
||||
cd CredentialManager
|
||||
dotnet ef migrations add [MigrationName]
|
||||
dotnet ef database update
|
||||
```
|
||||
|
||||
### Test Commands
|
||||
|
||||
#### Esecuzione Test Unitari
|
||||
```bash
|
||||
# Esecuzione tutti i test
|
||||
dotnet test Data_Coupler.sln
|
||||
|
||||
# Test con verbosità dettagliata
|
||||
dotnet test Data_Coupler.sln --verbosity detailed
|
||||
|
||||
# Test con coverage
|
||||
dotnet test Data_Coupler.sln --collect:"XPlat Code Coverage"
|
||||
|
||||
# Test specifici per progetto
|
||||
dotnet test DataConnection.Tests/DataConnection.Tests.csproj
|
||||
dotnet test CredentialManager.Tests/CredentialManager.Tests.csproj
|
||||
```
|
||||
|
||||
#### Test di Integrazione
|
||||
```bash
|
||||
# Test di integrazione database
|
||||
dotnet test --filter "Category=Integration"
|
||||
|
||||
# Test connessioni REST
|
||||
dotnet test --filter "Category=RestIntegration"
|
||||
|
||||
# Test end-to-end
|
||||
dotnet test --filter "Category=E2E"
|
||||
```
|
||||
|
||||
#### Performance Testing
|
||||
```bash
|
||||
# Benchmark performance
|
||||
dotnet run --project PerformanceTests/PerformanceTests.csproj --configuration Release
|
||||
|
||||
# Memory profiling
|
||||
dotnet run --project Data_Coupler/Data_Coupler.csproj --configuration Release
|
||||
# Utilizzare strumenti come dotMemory o PerfView
|
||||
```
|
||||
|
||||
## 📝 Code Style Guidelines
|
||||
|
||||
### Convenzioni di Naming
|
||||
|
||||
#### C# Naming Conventions
|
||||
```csharp
|
||||
// Classes e Interfaces: PascalCase
|
||||
public class DataConnectionFactory { }
|
||||
public interface IDatabaseManager { }
|
||||
|
||||
// Methods: PascalCase
|
||||
public async Task<List<Data>> GetDataAsync() { }
|
||||
|
||||
// Properties: PascalCase
|
||||
public string ConnectionString { get; set; }
|
||||
|
||||
// Private fields: camelCase con underscore
|
||||
private readonly ILogger _logger;
|
||||
|
||||
// Local variables e parameters: camelCase
|
||||
public void ProcessData(string connectionName, int batchSize) { }
|
||||
|
||||
// Constants: PascalCase
|
||||
public const string DefaultTimeout = "30";
|
||||
```
|
||||
|
||||
#### File e Directory Naming
|
||||
```
|
||||
// Cartelle: PascalCase
|
||||
Services/
|
||||
Models/
|
||||
Extensions/
|
||||
|
||||
// File C#: PascalCase con classe principale
|
||||
DatabaseConnectionService.cs
|
||||
CredentialEntity.cs
|
||||
|
||||
// File Razor: PascalCase
|
||||
DataCoupler.razor
|
||||
ProfileManagement.razor
|
||||
```
|
||||
|
||||
### Organizzazione Codice
|
||||
|
||||
#### Structure dei File
|
||||
```csharp
|
||||
using System; // System namespaces
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions; // Microsoft namespaces
|
||||
using DataConnection.Interfaces; // Project namespaces
|
||||
using ThirdParty.Library; // Third-party namespaces
|
||||
|
||||
namespace Data_Coupler.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Descrizione chiara della classe
|
||||
/// </summary>
|
||||
public class ExampleService : IExampleService
|
||||
{
|
||||
#region Private Fields
|
||||
private readonly ILogger<ExampleService> _logger;
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
public ExampleService(ILogger<ExampleService> logger)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public async Task<Result> ProcessAsync(Request request)
|
||||
{
|
||||
// Implementation
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void ValidateRequest(Request request)
|
||||
{
|
||||
// Validation logic
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Async/Await Pattern
|
||||
```csharp
|
||||
// ✅ Corretto
|
||||
public async Task<List<Data>> GetDataAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var data = await _repository.GetDataAsync(cancellationToken);
|
||||
return data.ToList();
|
||||
}
|
||||
|
||||
// ❌ Evitare
|
||||
public async Task<List<Data>> GetData()
|
||||
{
|
||||
var data = await _repository.GetDataAsync().Result; // Blocking call
|
||||
return data.ToList();
|
||||
}
|
||||
```
|
||||
|
||||
#### Error Handling
|
||||
```csharp
|
||||
// ✅ Gestione errori strutturata
|
||||
public async Task<Result<Data>> ProcessDataAsync(string input)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return Result<Data>.Failure("Input cannot be empty");
|
||||
|
||||
var data = await _service.ProcessAsync(input);
|
||||
return Result<Data>.Success(data);
|
||||
}
|
||||
catch (ValidationException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Validation failed for input: {Input}", input);
|
||||
return Result<Data>.Failure(ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unexpected error processing input: {Input}", input);
|
||||
return Result<Data>.Failure("An unexpected error occurred");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Dependency Injection Guidelines
|
||||
|
||||
#### Service Registration
|
||||
```csharp
|
||||
// Program.cs - Registrazione servizi
|
||||
// Singleton per servizi stateless
|
||||
builder.Services.AddSingleton<IEncryptionService, EncryptionService>();
|
||||
|
||||
// Scoped per servizi con stato per request
|
||||
builder.Services.AddScoped<IDataConnectionFactory, DataConnectionFactory>();
|
||||
|
||||
// Transient per servizi leggeri
|
||||
builder.Services.AddTransient<IValidator<Model>, ModelValidator>();
|
||||
```
|
||||
|
||||
#### Constructor Injection
|
||||
```csharp
|
||||
public class ProfileService
|
||||
{
|
||||
private readonly IDbContext _context;
|
||||
private readonly ILogger<ProfileService> _logger;
|
||||
private readonly IOptions<AppSettings> _options;
|
||||
|
||||
public ProfileService(
|
||||
IDbContext context,
|
||||
ILogger<ProfileService> logger,
|
||||
IOptions<AppSettings> options)
|
||||
{
|
||||
_context = context ?? throw new ArgumentNullException(nameof(context));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Commenti e Documentazione
|
||||
|
||||
#### XML Documentation
|
||||
```csharp
|
||||
/// <summary>
|
||||
/// Trasferisce dati da una sorgente a una destinazione utilizzando il mapping specificato
|
||||
/// </summary>
|
||||
/// <param name="sourceConnection">Connessione alla sorgente dati</param>
|
||||
/// <param name="destinationConnection">Connessione alla destinazione</param>
|
||||
/// <param name="mapping">Configurazione mapping campi</param>
|
||||
/// <param name="cancellationToken">Token per cancellazione operazione</param>
|
||||
/// <returns>Risultato del trasferimento con statistiche</returns>
|
||||
/// <exception cref="ArgumentNullException">Lanciata quando un parametro richiesto è null</exception>
|
||||
/// <exception cref="InvalidOperationException">Lanciata quando le connessioni non sono valide</exception>
|
||||
public async Task<TransferResult> TransferDataAsync(
|
||||
IDataConnection sourceConnection,
|
||||
IDataConnection destinationConnection,
|
||||
FieldMapping mapping,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// Implementation
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 Testing Instructions
|
||||
|
||||
### Struttura Test
|
||||
|
||||
#### Test Project Organization
|
||||
```
|
||||
Tests/
|
||||
├── Unit/ # Test unitari
|
||||
│ ├── Data_Coupler.Tests/
|
||||
│ ├── DataConnection.Tests/
|
||||
│ └── CredentialManager.Tests/
|
||||
├── Integration/ # Test di integrazione
|
||||
│ ├── Database.Integration.Tests/
|
||||
│ └── API.Integration.Tests/
|
||||
└── E2E/ # Test end-to-end
|
||||
└── UI.Tests/
|
||||
```
|
||||
|
||||
### Test Unitari
|
||||
|
||||
#### Setup Test Class
|
||||
```csharp
|
||||
[TestClass]
|
||||
public class CredentialServiceTests
|
||||
{
|
||||
private Mock<IDbContext> _mockContext;
|
||||
private Mock<IEncryptionService> _mockEncryption;
|
||||
private Mock<ILogger<CredentialService>> _mockLogger;
|
||||
private CredentialService _service;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
_mockContext = new Mock<IDbContext>();
|
||||
_mockEncryption = new Mock<IEncryptionService>();
|
||||
_mockLogger = new Mock<ILogger<CredentialService>>();
|
||||
|
||||
_service = new CredentialService(
|
||||
_mockContext.Object,
|
||||
_mockEncryption.Object,
|
||||
_mockLogger.Object);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
_service?.Dispose();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Test Methods Pattern
|
||||
```csharp
|
||||
[TestMethod]
|
||||
public async Task GetCredentialAsync_WithValidName_ReturnsCredential()
|
||||
{
|
||||
// Arrange
|
||||
var credentialName = "TestCredential";
|
||||
var expectedCredential = new CredentialEntity { Name = credentialName };
|
||||
|
||||
_mockContext.Setup(x => x.Credentials.FirstOrDefaultAsync(
|
||||
It.IsAny<Expression<Func<CredentialEntity, bool>>>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(expectedCredential);
|
||||
|
||||
// Act
|
||||
var result = await _service.GetCredentialAsync(credentialName);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(credentialName, result.Name);
|
||||
_mockContext.Verify(x => x.Credentials.FirstOrDefaultAsync(
|
||||
It.IsAny<Expression<Func<CredentialEntity, bool>>>(),
|
||||
It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetCredentialAsync_WithNullName_ThrowsArgumentNullException()
|
||||
{
|
||||
// Act & Assert
|
||||
await Assert.ThrowsExceptionAsync<ArgumentNullException>(
|
||||
() => _service.GetCredentialAsync(null));
|
||||
}
|
||||
```
|
||||
|
||||
### Test di Integrazione
|
||||
|
||||
#### Database Integration Tests
|
||||
```csharp
|
||||
[TestClass]
|
||||
public class DatabaseIntegrationTests
|
||||
{
|
||||
private TestDatabase _testDb;
|
||||
private IDatabaseManager _databaseManager;
|
||||
|
||||
[TestInitialize]
|
||||
public async Task Setup()
|
||||
{
|
||||
_testDb = await TestDatabase.CreateAsync();
|
||||
_databaseManager = new EFCoreDatabaseManager(_testDb.ConnectionString);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public async Task Cleanup()
|
||||
{
|
||||
await _testDb.DisposeAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ExecuteQueryAsync_WithValidQuery_ReturnsData()
|
||||
{
|
||||
// Arrange
|
||||
await _testDb.SeedDataAsync();
|
||||
var query = "SELECT * FROM TestTable WHERE Id = 1";
|
||||
|
||||
// Act
|
||||
var result = await _databaseManager.ExecuteQueryAsync<TestEntity>(query);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.IsTrue(result.Any());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### REST API Integration Tests
|
||||
```csharp
|
||||
[TestClass]
|
||||
public class RestApiIntegrationTests
|
||||
{
|
||||
private TestServer _testServer;
|
||||
private HttpClient _client;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder();
|
||||
// Configure test server
|
||||
_testServer = new TestServer(builder);
|
||||
_client = _testServer.CreateClient();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetData_WithValidCredentials_ReturnsSuccess()
|
||||
{
|
||||
// Arrange
|
||||
var apiClient = new GenericRestServiceClient(_client);
|
||||
|
||||
// Act
|
||||
var result = await apiClient.GetAsync<ApiResponse>("/api/data");
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
Assert.IsTrue(result.Success);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test End-to-End
|
||||
|
||||
#### Playwright UI Tests
|
||||
```csharp
|
||||
[TestClass]
|
||||
public class UITests
|
||||
{
|
||||
private IPlaywright _playwright;
|
||||
private IBrowser _browser;
|
||||
private IPage _page;
|
||||
|
||||
[TestInitialize]
|
||||
public async Task Setup()
|
||||
{
|
||||
_playwright = await Playwright.CreateAsync();
|
||||
_browser = await _playwright.Chromium.LaunchAsync();
|
||||
_page = await _browser.NewPageAsync();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task DataTransfer_CompleteWorkflow_Success()
|
||||
{
|
||||
// Navigate to application
|
||||
await _page.GotoAsync("http://localhost:7550");
|
||||
|
||||
// Configure source connection
|
||||
await _page.ClickAsync("#source-database-tab");
|
||||
await _page.FillAsync("#connection-name", "TestConnection");
|
||||
|
||||
// Configure mapping
|
||||
await _page.ClickAsync("#next-step");
|
||||
|
||||
// Execute transfer
|
||||
await _page.ClickAsync("#execute-transfer");
|
||||
|
||||
// Verify results
|
||||
var successMessage = await _page.WaitForSelectorAsync(".success-message");
|
||||
Assert.IsNotNull(successMessage);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test Configuration
|
||||
|
||||
#### appsettings.Test.json
|
||||
```json
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Data Source=:memory:",
|
||||
"TestDatabase": "Server=(localdb)\\mssqllocaldb;Database=DataCouplerTest;Trusted_Connection=true;"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"Microsoft": "Warning"
|
||||
}
|
||||
},
|
||||
"TestSettings": {
|
||||
"UseInMemoryDatabase": true,
|
||||
"MockExternalServices": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test Execution Scripts
|
||||
|
||||
#### PowerShell Test Runner
|
||||
```powershell
|
||||
# run-tests.ps1
|
||||
param(
|
||||
[string]$Configuration = "Debug",
|
||||
[string]$Filter = "",
|
||||
[switch]$Coverage
|
||||
)
|
||||
|
||||
Write-Host "Running tests..." -ForegroundColor Green
|
||||
|
||||
if ($Coverage) {
|
||||
dotnet test Data_Coupler.sln `
|
||||
--configuration $Configuration `
|
||||
--collect:"XPlat Code Coverage" `
|
||||
--results-directory TestResults `
|
||||
--filter $Filter
|
||||
|
||||
# Generate coverage report
|
||||
reportgenerator `
|
||||
-reports:"TestResults/*/coverage.cobertura.xml" `
|
||||
-targetdir:"TestResults/CoverageReport" `
|
||||
-reporttypes:Html
|
||||
} else {
|
||||
dotnet test Data_Coupler.sln `
|
||||
--configuration $Configuration `
|
||||
--filter $Filter
|
||||
}
|
||||
```
|
||||
|
||||
## 🔒 Security Considerations
|
||||
|
||||
### Gestione Credenziali
|
||||
|
||||
#### Crittografia dei Dati Sensibili
|
||||
```csharp
|
||||
public class EncryptionService : IEncryptionService
|
||||
{
|
||||
private readonly IDataProtector _protector;
|
||||
|
||||
public EncryptionService(IDataProtectionProvider provider)
|
||||
{
|
||||
_protector = provider.CreateProtector("DataCoupler.Credentials.v1");
|
||||
}
|
||||
|
||||
public string Encrypt(string plaintext)
|
||||
{
|
||||
if (string.IsNullOrEmpty(plaintext))
|
||||
return plaintext;
|
||||
|
||||
return _protector.Protect(plaintext);
|
||||
}
|
||||
|
||||
public string Decrypt(string ciphertext)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ciphertext))
|
||||
return ciphertext;
|
||||
|
||||
try
|
||||
{
|
||||
return _protector.Unprotect(ciphertext);
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
// Handle decryption failure
|
||||
throw new SecurityException("Failed to decrypt data");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Configurazione Data Protection
|
||||
```csharp
|
||||
// Program.cs
|
||||
builder.Services.AddDataProtection()
|
||||
.PersistKeysToFileSystem(new DirectoryInfo(keyPath))
|
||||
.SetApplicationName("DataCoupler")
|
||||
.SetDefaultKeyLifetime(TimeSpan.FromDays(90));
|
||||
```
|
||||
|
||||
### Validazione Input
|
||||
|
||||
#### SQL Injection Prevention
|
||||
```csharp
|
||||
// ✅ Parametrized Queries
|
||||
public async Task<List<Entity>> GetDataAsync(string tableName, int id)
|
||||
{
|
||||
// Validate table name against whitelist
|
||||
if (!IsValidTableName(tableName))
|
||||
throw new ArgumentException("Invalid table name");
|
||||
|
||||
var query = $"SELECT * FROM [{tableName}] WHERE Id = @id";
|
||||
var parameters = new { id };
|
||||
|
||||
return await _connection.QueryAsync<Entity>(query, parameters);
|
||||
}
|
||||
|
||||
// ❌ Mai utilizzare string concatenation
|
||||
public async Task<List<Entity>> GetDataUnsafe(string tableName, int id)
|
||||
{
|
||||
var query = $"SELECT * FROM {tableName} WHERE Id = {id}"; // VULNERABLE
|
||||
return await _connection.QueryAsync<Entity>(query);
|
||||
}
|
||||
```
|
||||
|
||||
#### Input Sanitization
|
||||
```csharp
|
||||
public class InputValidator
|
||||
{
|
||||
private static readonly Regex AllowedTableName = new(@"^[a-zA-Z][a-zA-Z0-9_]*$");
|
||||
private static readonly Regex AllowedFieldName = new(@"^[a-zA-Z][a-zA-Z0-9_]*$");
|
||||
|
||||
public static bool IsValidTableName(string tableName)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(tableName) &&
|
||||
tableName.Length <= 128 &&
|
||||
AllowedTableName.IsMatch(tableName);
|
||||
}
|
||||
|
||||
public static bool IsValidFieldName(string fieldName)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(fieldName) &&
|
||||
fieldName.Length <= 128 &&
|
||||
AllowedFieldName.IsMatch(fieldName);
|
||||
}
|
||||
|
||||
public static string SanitizeStringInput(string input, int maxLength = 255)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
return string.Empty;
|
||||
|
||||
// Remove potential XSS characters
|
||||
input = input.Replace("<", "<")
|
||||
.Replace(">", ">")
|
||||
.Replace("\"", """)
|
||||
.Replace("'", "'")
|
||||
.Replace("/", "/");
|
||||
|
||||
return input.Length > maxLength ? input.Substring(0, maxLength) : input;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Autenticazione e Autorizzazione
|
||||
|
||||
#### Connection Security
|
||||
```csharp
|
||||
public class SecureConnectionFactory : IDataConnectionFactory
|
||||
{
|
||||
public async Task<IDatabaseManager> CreateDatabaseManagerAsync(string credentialName)
|
||||
{
|
||||
var credential = await _credentialService.GetCredentialAsync(credentialName);
|
||||
if (credential == null)
|
||||
throw new UnauthorizedAccessException("Credential not found");
|
||||
|
||||
// Validate credential permissions
|
||||
if (!await ValidateCredentialPermissions(credential))
|
||||
throw new UnauthorizedAccessException("Insufficient permissions");
|
||||
|
||||
// Create connection with timeout
|
||||
var connectionString = BuildSecureConnectionString(credential);
|
||||
return new DatabaseManager(connectionString);
|
||||
}
|
||||
|
||||
private string BuildSecureConnectionString(CredentialEntity credential)
|
||||
{
|
||||
var builder = new SqlConnectionStringBuilder
|
||||
{
|
||||
DataSource = credential.Host,
|
||||
InitialCatalog = credential.DatabaseName,
|
||||
UserID = credential.Username,
|
||||
Password = _encryptionService.Decrypt(credential.EncryptedPassword),
|
||||
|
||||
// Security settings
|
||||
Encrypt = true,
|
||||
TrustServerCertificate = false,
|
||||
ConnectTimeout = 30,
|
||||
CommandTimeout = 300
|
||||
};
|
||||
|
||||
return builder.ConnectionString;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### HTTPS e Comunicazioni Sicure
|
||||
|
||||
#### HTTPS Configuration
|
||||
```csharp
|
||||
// Program.cs
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseHsts();
|
||||
app.UseHttpsRedirection();
|
||||
}
|
||||
|
||||
// Force HTTPS in production
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
if (!context.Request.IsHttps && !app.Environment.IsDevelopment())
|
||||
{
|
||||
var httpsUrl = $"https://{context.Request.Host}{context.Request.Path}{context.Request.QueryString}";
|
||||
context.Response.Redirect(httpsUrl, permanent: true);
|
||||
return;
|
||||
}
|
||||
await next();
|
||||
});
|
||||
```
|
||||
|
||||
#### HTTP Client Security
|
||||
```csharp
|
||||
public class SecureHttpClientFactory
|
||||
{
|
||||
public HttpClient CreateSecureClient(RestCredentialSettings settings)
|
||||
{
|
||||
var handler = new HttpClientHandler();
|
||||
|
||||
if (!settings.IgnoreSslErrors)
|
||||
{
|
||||
handler.ServerCertificateCustomValidationCallback =
|
||||
(sender, cert, chain, sslPolicyErrors) =>
|
||||
{
|
||||
// Validate certificate chain
|
||||
return sslPolicyErrors == SslPolicyErrors.None;
|
||||
};
|
||||
}
|
||||
|
||||
var client = new HttpClient(handler)
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(settings.TimeoutSeconds)
|
||||
};
|
||||
|
||||
// Add security headers
|
||||
client.DefaultRequestHeaders.Add("User-Agent", "DataCoupler/1.0");
|
||||
client.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Logging e Audit
|
||||
|
||||
#### Secure Logging
|
||||
```csharp
|
||||
public class SecurityAuditLogger
|
||||
{
|
||||
private readonly ILogger<SecurityAuditLogger> _logger;
|
||||
|
||||
public void LogCredentialAccess(string credentialName, string operation, string userId)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Credential Access: {Operation} on {CredentialName} by {UserId} at {Timestamp}",
|
||||
operation, credentialName, userId, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
public void LogDataTransfer(string sourceType, string destinationType, int recordCount, string userId)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Data Transfer: {RecordCount} records from {SourceType} to {DestinationType} by {UserId} at {Timestamp}",
|
||||
recordCount, sourceType, destinationType, userId, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
public void LogSecurityEvent(string eventType, string details, string userId)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Security Event: {EventType} - {Details} by {UserId} at {Timestamp}",
|
||||
eventType, details, userId, DateTime.UtcNow);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling Sicuro
|
||||
|
||||
#### Information Disclosure Prevention
|
||||
```csharp
|
||||
public class SecureErrorHandler
|
||||
{
|
||||
private readonly ILogger<SecureErrorHandler> _logger;
|
||||
|
||||
public ErrorResponse HandleError(Exception ex, bool isDevelopment)
|
||||
{
|
||||
// Log full error details
|
||||
_logger.LogError(ex, "Error occurred: {Message}", ex.Message);
|
||||
|
||||
// Return sanitized error to client
|
||||
if (isDevelopment)
|
||||
{
|
||||
return new ErrorResponse
|
||||
{
|
||||
Message = ex.Message,
|
||||
StackTrace = ex.StackTrace,
|
||||
Type = ex.GetType().Name
|
||||
};
|
||||
}
|
||||
|
||||
// Production: return generic message
|
||||
return new ErrorResponse
|
||||
{
|
||||
Message = "An error occurred while processing your request",
|
||||
ErrorId = Guid.NewGuid().ToString() // For correlation
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Database Security
|
||||
|
||||
#### Connection Security
|
||||
```csharp
|
||||
public class DatabaseSecuritySettings
|
||||
{
|
||||
public static SqlConnectionStringBuilder CreateSecureConnectionString(
|
||||
string server, string database, string username, string password)
|
||||
{
|
||||
return new SqlConnectionStringBuilder
|
||||
{
|
||||
DataSource = server,
|
||||
InitialCatalog = database,
|
||||
UserID = username,
|
||||
Password = password,
|
||||
|
||||
// Security settings
|
||||
Encrypt = true,
|
||||
TrustServerCertificate = false,
|
||||
IntegratedSecurity = false,
|
||||
MultipleActiveResultSets = false,
|
||||
|
||||
// Timeout settings
|
||||
ConnectTimeout = 30,
|
||||
CommandTimeout = 300,
|
||||
|
||||
// Connection pooling
|
||||
Pooling = true,
|
||||
MinPoolSize = 0,
|
||||
MaxPoolSize = 100
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Versione**: 1.0
|
||||
**Ultimo Aggiornamento**: Settembre 2025
|
||||
**Framework**: .NET 9.0
|
||||
**Sviluppatore**: Alessio Dalsanto
|
||||
@@ -1,591 +0,0 @@
|
||||
# Data-Coupler: Documentazione Completa del Progetto
|
||||
|
||||
## Indice
|
||||
1. [Descrizione Generale del Progetto](#descrizione-generale-del-progetto)
|
||||
2. [Architettura e Struttura del Progetto](#architettura-e-struttura-del-progetto)
|
||||
3. [Mappatura dei Progetti della Soluzione](#mappatura-dei-progetti-della-soluzione)
|
||||
4. [Funzionalità Dettagliate](#funzionalità-dettagliate)
|
||||
5. [Mappa delle Funzioni e Procedure](#mappa-delle-funzioni-e-procedure)
|
||||
6. [Riferimenti Esterni e Percorsi](#riferimenti-esterni-e-percorsi)
|
||||
7. [Interconnessioni tra Componenti](#interconnessioni-tra-componenti)
|
||||
8. [Stato delle Implementazioni](#stato-delle-implementazioni)
|
||||
9. [Utilizzo e Configurazione](#utilizzo-e-configurazione)
|
||||
|
||||
---
|
||||
|
||||
## Descrizione Generale del Progetto
|
||||
|
||||
**Data-Coupler** è un sistema avanzato per l'accoppiamento e sincronizzazione di dati tra diverse fonti di dati e destinazioni. Il progetto è sviluppato in .NET 9.0 utilizzando Blazor Server e fornisce un'interfaccia web intuitiva per configurare, gestire ed eseguire operazioni di trasferimento dati.
|
||||
|
||||
### Funzionalità Principali
|
||||
- **Connessione Multi-Database**: Supporta SQL Server, MySQL, PostgreSQL, Oracle, SQLite, DB2, SAP HANA
|
||||
- **Integrazione REST API**: Supporta API generiche, Salesforce, SAP Business One Service Layer
|
||||
- **Elaborazione File**: Gestisce file Excel (.xlsx, .xls) e CSV
|
||||
- **Sistema di Mapping**: Mappatura intelligente dei campi tra sorgenti e destinazioni
|
||||
- **Gestione Associazioni**: Sistema di tracking delle chiavi per evitare duplicati
|
||||
- **Gestione Profili**: Salvataggio e riutilizzo di configurazioni
|
||||
- **Background Services**: Servizi in background per operazioni periodiche
|
||||
- **Sicurezza**: Crittografia delle credenziali cross-platform
|
||||
|
||||
### Caratteristiche Tecniche
|
||||
- **Framework**: .NET 9.0, Blazor Server
|
||||
- **Database**: SQLite con Entity Framework Core
|
||||
- **UI**: Bootstrap 5, Font Awesome
|
||||
- **Architettura**: Modulare con separazione delle responsabilità
|
||||
- **Cross-Platform**: Windows, Linux, macOS
|
||||
|
||||
---
|
||||
|
||||
## Architettura e Struttura del Progetto
|
||||
|
||||
Il progetto segue un'architettura modulare con separazione chiara delle responsabilità:
|
||||
|
||||
```
|
||||
Data-Coupler/
|
||||
├── Data_Coupler/ # Applicazione principale Blazor Server
|
||||
├── DataConnection/ # Libreria per connessioni dati
|
||||
├── CredentialManager/ # Gestione sicura delle credenziali
|
||||
├── Components/ # Componenti UI riutilizzabili
|
||||
└── Documentation/ # File di documentazione
|
||||
```
|
||||
|
||||
### Principi Architetturali
|
||||
1. **Separation of Concerns**: Ogni progetto ha responsabilità specifiche
|
||||
2. **Dependency Injection**: Utilizzo estensivo di DI per loose coupling
|
||||
3. **Factory Pattern**: Per la creazione di connessioni database e REST
|
||||
4. **Repository Pattern**: Per l'accesso ai dati
|
||||
5. **Service Layer**: Logica business separata dalla presentazione
|
||||
|
||||
---
|
||||
|
||||
## Mappatura dei Progetti della Soluzione
|
||||
|
||||
### 1. Data_Coupler (Progetto Principale)
|
||||
**Tipo**: Applicazione Web Blazor Server
|
||||
**Tecnologie**: .NET 9.0, Blazor Server, Bootstrap 5
|
||||
**Responsabilità**: Interfaccia utente principale e orchestrazione
|
||||
|
||||
#### Strutture Principali:
|
||||
- **Pages/**: Pagine Blazor per le diverse funzionalità
|
||||
- `DataCoupler.razor(.cs)`: Pagina principale per il trasferimento dati
|
||||
- `ProfilesManagement.razor(.cs)`: Gestione dei profili salvati
|
||||
- `CredentialManagement.razor`: Gestione delle credenziali
|
||||
- `KeyAssociations.razor`: Gestione delle associazioni chiavi
|
||||
- **Extensions/DataCoupler/**: Metodi estesi per funzionalità specifiche
|
||||
- `DatabaseMethod.cs`: Metodi per connessioni database
|
||||
- `RESTMethod.cs`: Metodi per connessioni REST API
|
||||
- **Services/**: Servizi dell'applicazione
|
||||
- `DataConnectionFactory.cs`: Factory per connessioni dati
|
||||
- **Models/**: Modelli di dati specifici dell'app
|
||||
- `DataCouplerModels.cs`: Modelli per risultati trasferimenti
|
||||
- **BackgroundServices/**: Servizi in background
|
||||
- `BackgroundServices.cs`: Servizi periodici (attualmente placeholder)
|
||||
|
||||
### 2. DataConnection (Libreria Core)
|
||||
**Tipo**: Class Library
|
||||
**Responsabilità**: Gestione connessioni database e REST API
|
||||
|
||||
#### Strutture Principali:
|
||||
- **DB/**: Gestione database
|
||||
- **Interfaces/**: Interfacce per abstraction layer
|
||||
- `IDatabaseManager.cs`: Interfaccia principale per database
|
||||
- `IDatabaseSchemaProvider.cs`: Provider per schema discovery
|
||||
- `IDatabaseDiscovery.cs`: Discovery di database disponibili
|
||||
- **EF/**: Implementazioni Entity Framework
|
||||
- `EFCoreDatabaseManager.cs`: Manager EF Core per database esistenti
|
||||
- **DatabaseDiscovery/**: Discovery specifiche per DB type
|
||||
- **REST/**: Gestione REST API
|
||||
- **Interfaces/**: Interfacce REST
|
||||
- **Implementations/**: Implementazioni specifiche (Salesforce, Generic)
|
||||
- **Models/**: Modelli per richieste/risposte REST
|
||||
- **CredentialManagement/**: Integrazione con CredentialManager
|
||||
|
||||
### 3. CredentialManager (Gestione Credenziali)
|
||||
**Tipo**: Class Library
|
||||
**Responsabilità**: Gestione sicura delle credenziali
|
||||
|
||||
#### Strutture Principali:
|
||||
- **Data/**: Contesto Entity Framework
|
||||
- `CredentialDbContext.cs`: DbContext per credenziali
|
||||
- **Models/**: Modelli di dati
|
||||
- `CredentialModels.cs`: DTOs per credenziali
|
||||
- `CredentialEntity.cs`: Entità database
|
||||
- `KeyAssociation.cs`: Modello per associazioni chiavi
|
||||
- `DataCouplerProfile.cs`: Modello per profili salvati
|
||||
- **Services/**: Servizi di gestione
|
||||
- `CredentialService.cs`: Servizio principale per credenziali
|
||||
- `DataCouplerProfileService.cs`: Gestione profili
|
||||
- **Utilities/**: Utilità varie
|
||||
- `EncryptionService.cs`: Crittografia cross-platform
|
||||
- **Integration/**: Helper per integrazione
|
||||
- `DataConnectionHelper.cs`: Utilità per DataConnection
|
||||
|
||||
### 4. Components (Componenti UI)
|
||||
**Tipo**: Razor Class Library
|
||||
**Responsabilità**: Componenti UI riutilizzabili
|
||||
|
||||
#### Componenti Principali:
|
||||
- `ProfileManagement.razor(.cs)`: Componente per gestione profili
|
||||
- `ProfileSelector.razor(.cs)`: Selettore di profili
|
||||
- `ProfileSaver.razor(.cs)`: Componente per salvare profili
|
||||
|
||||
---
|
||||
|
||||
## Funzionalità Dettagliate
|
||||
|
||||
### 1. Gestione Sorgenti Dati
|
||||
|
||||
#### Connessioni Database
|
||||
- **Supporto Multi-DB**: SQL Server, MySQL, PostgreSQL, Oracle, SQLite, DB2, SAP HANA
|
||||
- **Schema Discovery**: Automatic discovery di tabelle, colonne e metadati
|
||||
- **Query Custom**: Supporto per query SQL personalizzate
|
||||
- **Connection String Generation**: Generazione automatica connection string
|
||||
- **Test Connessioni**: Validazione connessioni prima dell'uso
|
||||
|
||||
#### Elaborazione File
|
||||
- **Formati Supportati**: Excel (.xlsx, .xls), CSV
|
||||
- **Multi-Sheet**: Gestione fogli multipli in Excel
|
||||
- **Preview Data**: Anteprima dati con paginazione
|
||||
- **Encoding Detection**: Rilevamento automatico encoding
|
||||
|
||||
#### Connessioni REST API
|
||||
- **API Generiche**: Supporto per REST API standard
|
||||
- **Salesforce**: Integrazione specifica con autenticazione OAuth
|
||||
- **SAP B1 Service Layer**: Integrazione con SAP Business One
|
||||
- **Composite API**: Ottimizzazione per operazioni batch (Salesforce)
|
||||
|
||||
### 2. Sistema di Mapping
|
||||
|
||||
#### Mapping Campi
|
||||
- **Drag & Drop**: Interfaccia intuitiva per mapping
|
||||
- **Auto-Detection**: Rilevamento automatico campi simili
|
||||
- **Validazione**: Controllo compatibilità tipi dati
|
||||
- **Preview**: Anteprima risultati mapping
|
||||
|
||||
#### Gestione Chiavi
|
||||
- **Chiavi Sorgente**: Identificazione univoca record sorgente
|
||||
- **Chiavi Destinazione**: Tracking ID destinazione
|
||||
- **Associazioni**: Sistema di associazioni per evitare duplicati
|
||||
- **Hash Verification**: Controllo modifiche tramite hash dati
|
||||
|
||||
### 3. Trasferimento Dati
|
||||
|
||||
#### Modalità di Trasferimento
|
||||
- **Insert**: Creazione nuovi record
|
||||
- **Update**: Aggiornamento record esistenti
|
||||
- **Upsert**: Insert o update automatico
|
||||
- **Batch Processing**: Elaborazione in lotti per performance
|
||||
|
||||
#### Gestione Errori
|
||||
- **Logging Dettagliato**: Log completi di ogni operazione
|
||||
- **Error Handling**: Gestione granulare degli errori
|
||||
- **Rollback**: Possibilità di rollback operazioni
|
||||
- **Report Risultati**: Report dettagliati successi/errori
|
||||
|
||||
### 4. Gestione Profili
|
||||
|
||||
#### Salvataggio Configurazioni
|
||||
- **Profili Completi**: Salvataggio di tutte le configurazioni
|
||||
- **Metadati**: Nome, descrizione, data creazione/utilizzo
|
||||
- **Versioning**: Gestione versioni profili
|
||||
- **Export/Import**: Esportazione profili in JSON
|
||||
|
||||
#### Gestione Profili
|
||||
- **Lista Profili**: Visualizzazione tutti i profili salvati
|
||||
- **Filtri**: Ricerca per nome, tipo, utilizzo
|
||||
- **Statistiche**: Dashboard con statistiche utilizzo
|
||||
- **Eliminazione**: Soft delete profili
|
||||
|
||||
---
|
||||
|
||||
## Mappa delle Funzioni e Procedure
|
||||
|
||||
### Data_Coupler.Pages.DataCoupler
|
||||
|
||||
#### Metodi di Gestione Stato
|
||||
- `OnInitializedAsync()`: Inizializzazione componente
|
||||
- `LoadCredentials()`: Caricamento credenziali database/REST
|
||||
- `LoadProfiles()`: Caricamento profili disponibili
|
||||
- `ResetAllState()`: Reset completo stato applicazione
|
||||
|
||||
#### Metodi Database (DatabaseMethod.cs)
|
||||
- `ConnectToDatabase()`: Connessione database principale
|
||||
- `ConnectToDatabaseWithSpecificDatabase(string)`: Connessione a DB specifico
|
||||
- `ConnectToDatabaseWithSchema(string)`: Connessione con schema specifico
|
||||
- `LoadTablesFromConnectedDatabase()`: Caricamento tabelle
|
||||
- `LoadAvailableDatabases()`: Discovery database disponibili
|
||||
- `SelectTable(string)`: Selezione tabella e caricamento schema
|
||||
- `ValidateCustomQuery()`: Validazione query personalizzate
|
||||
- `LoadQueryPreview()`: Anteprima risultati query
|
||||
|
||||
#### Metodi REST (RESTMethod.cs)
|
||||
- `ConnectToRestService()`: Connessione servizio REST
|
||||
- `LoadRestMetadata()`: Caricamento metadati REST
|
||||
- `TestRestConnection()`: Test connessione REST API
|
||||
|
||||
#### Metodi File
|
||||
- `ProcessFileUpload()`: Elaborazione file caricati
|
||||
- `LoadFileData()`: Lettura dati da file
|
||||
- `ParseExcelFile()`: Parsing file Excel
|
||||
- `ParseCsvFile()`: Parsing file CSV
|
||||
|
||||
#### Metodi Mapping
|
||||
- `MapField(string, string)`: Mapping singolo campo
|
||||
- `RemoveMapping(string)`: Rimozione mapping
|
||||
- `ClearAllMappings()`: Reset tutti i mapping
|
||||
- `ValidateMapping()`: Validazione configurazione mapping
|
||||
- `AutoMapFields()`: Auto-mapping campi simili
|
||||
|
||||
#### Metodi Trasferimento
|
||||
- `StartDataTransfer()`: Avvio trasferimento standard
|
||||
- `StartDataTransferWithComposite()`: Trasferimento con Composite API
|
||||
- `ProcessRecord()`: Elaborazione singolo record
|
||||
- `CreateAssociationAsync()`: Creazione associazione chiave
|
||||
- `UpdateAssociationHashAsync()`: Aggiornamento hash associazione
|
||||
|
||||
#### Metodi Profili
|
||||
- `OnProfileLoaded()`: Caricamento profilo salvato
|
||||
- `ApplyProfileConfiguration()`: Applicazione configurazione profilo
|
||||
- `SaveCurrentProfile()`: Salvataggio profilo corrente
|
||||
|
||||
### DataConnection.EF.EFCoreDatabaseManager
|
||||
|
||||
#### Metodi Core
|
||||
- `TestConnectionAsync()`: Test connessione database
|
||||
- `GetDatabaseSchemaAsync()`: Recupero schema completo
|
||||
- `GetAvailableDatabasesAsync()`: Lista database disponibili
|
||||
- `ChangeDatabaseAsync(string)`: Cambio database corrente
|
||||
|
||||
#### Metodi CRUD Generici
|
||||
- `GetAsync<T>()`: Query generiche con filtri
|
||||
- `GetByIdAsync<T>(object)`: Recupero per ID
|
||||
- `CreateAsync<T>(T)`: Creazione entity
|
||||
- `UpdateAsync<T>(T)`: Aggiornamento entity
|
||||
- `DeleteAsync<T>(T)`: Eliminazione entity
|
||||
|
||||
#### Metodi SQL Raw
|
||||
- `ExecuteRawSqlAsync(string, object[])`: Esecuzione SQL raw
|
||||
- `ExecuteCommandAsync(string, object[])`: Comandi SQL
|
||||
|
||||
### CredentialManager.Services.CredentialService
|
||||
|
||||
#### Gestione Credenziali Database
|
||||
- `SaveDatabaseCredentialAsync()`: Salvataggio credenziali DB
|
||||
- `GetDatabaseCredentialAsync()`: Recupero credenziali DB
|
||||
- `GetAllDatabaseCredentialsAsync()`: Lista tutte credenziali DB
|
||||
- `TestDatabaseConnectionAsync()`: Test connessione DB
|
||||
|
||||
#### Gestione Credenziali REST
|
||||
- `SaveRestApiCredentialAsync()`: Salvataggio credenziali REST
|
||||
- `GetRestApiCredentialAsync()`: Recupero credenziali REST
|
||||
- `GetAllRestApiCredentialsAsync()`: Lista tutte credenziali REST
|
||||
- `TestRestConnectionAsync()`: Test connessione REST
|
||||
|
||||
#### Gestione Associazioni Chiavi
|
||||
- `SaveKeyAssociationAsync()`: Salvataggio associazione
|
||||
- `FindKeyAssociationByValueAsync()`: Ricerca per valore chiave
|
||||
- `UpdateKeyAssociationAsync()`: Aggiornamento associazione
|
||||
- `GetKeyAssociationsAsync()`: Lista associazioni
|
||||
|
||||
### CredentialManager.Services.DataCouplerProfileService
|
||||
|
||||
#### Gestione Profili
|
||||
- `SaveProfileAsync()`: Salvataggio nuovo profilo
|
||||
- `UpdateProfileAsync()`: Aggiornamento profilo esistente
|
||||
- `GetAllProfilesAsync()`: Lista tutti i profili
|
||||
- `GetProfileByIdAsync()`: Recupero profilo per ID
|
||||
- `GetProfileByNameAsync()`: Recupero profilo per nome
|
||||
- `DeleteProfileAsync()`: Eliminazione profilo (soft delete)
|
||||
- `UpdateLastUsedAsync()`: Aggiornamento ultimo utilizzo
|
||||
|
||||
#### Utilità Profili
|
||||
- `ProfileExistsAsync()`: Verifica esistenza profilo
|
||||
- `SerializeFieldMappings()`: Serializzazione mapping
|
||||
- `DeserializeFieldMappings()`: Deserializzazione mapping
|
||||
- `ToDto()`: Conversione a DTO
|
||||
- `FromDto()`: Conversione da DTO
|
||||
|
||||
---
|
||||
|
||||
## Riferimenti Esterni e Percorsi
|
||||
|
||||
### Database SQLite Principale
|
||||
**Percorso**:
|
||||
- **Windows**: `%ProgramData%\Data_Coupler\credentials.db`
|
||||
- **Linux**: `/var/lib/Data_Coupler/credentials.db`
|
||||
- **macOS**: `/Library/Application Support/Data_Coupler/credentials.db`
|
||||
|
||||
### Tabelle Database
|
||||
1. **Credentials**: Memorizzazione credenziali crittografate
|
||||
2. **KeyAssociations**: Associazioni chiavi sorgente-destinazione
|
||||
3. **DataCouplerProfiles**: Profili di configurazione salvati
|
||||
|
||||
### File di Configurazione
|
||||
- `appsettings.json`: Configurazione generale
|
||||
- `appsettings.Development.json`: Configurazione sviluppo
|
||||
- `nuget.config`: Configurazione pacchetti NuGet
|
||||
|
||||
### Dipendenze Esterne Principali
|
||||
- **Microsoft.EntityFrameworkCore**: ORM per database
|
||||
- **ExcelDataReader**: Lettura file Excel
|
||||
- **System.Data.SqlClient**: SQL Server
|
||||
- **MySqlConnector**: MySQL
|
||||
- **Npgsql**: PostgreSQL
|
||||
- **Oracle.ManagedDataAccess**: Oracle
|
||||
- **IBM.Data.Db2**: DB2
|
||||
|
||||
### Porte di Default
|
||||
- **Applicazione Web**: `http://localhost:7550`
|
||||
- **SQL Server**: 1433
|
||||
- **MySQL**: 3306
|
||||
- **PostgreSQL**: 5432
|
||||
- **Oracle**: 1521
|
||||
|
||||
---
|
||||
|
||||
## Interconnessioni tra Componenti
|
||||
|
||||
### Flusso di Dipendenze
|
||||
```
|
||||
Data_Coupler (App)
|
||||
├── CredentialManager (Gestione Credenziali)
|
||||
├── DataConnection (Connessioni Dati)
|
||||
├── Components (UI Components)
|
||||
└── Background Services
|
||||
```
|
||||
|
||||
### Interazioni Principali
|
||||
|
||||
#### 1. Caricamento Credenziali
|
||||
```
|
||||
Data_Coupler → CredentialManager.CredentialService → SQLite Database
|
||||
```
|
||||
|
||||
#### 2. Connessione Database
|
||||
```
|
||||
Data_Coupler → DataConnectionFactory → DataConnection.EF.EFCoreDatabaseManager → Database Target
|
||||
```
|
||||
|
||||
#### 3. Connessione REST
|
||||
```
|
||||
Data_Coupler → DataConnectionFactory → DataConnection.REST.Implementations → REST API
|
||||
```
|
||||
|
||||
#### 4. Gestione Profili
|
||||
```
|
||||
Data_Coupler → CredentialManager.DataCouplerProfileService → SQLite Database
|
||||
```
|
||||
|
||||
### Pattern di Comunicazione
|
||||
|
||||
#### Dependency Injection
|
||||
Tutti i servizi sono registrati nel container DI e iniettati dove necessario:
|
||||
```csharp
|
||||
// Program.cs
|
||||
builder.Services.AddDataConnectionCredentialManagement(dbPath);
|
||||
builder.Services.AddScoped<IDataConnectionFactory, DataConnectionFactory>();
|
||||
```
|
||||
|
||||
#### Factory Pattern
|
||||
Le connessioni sono create tramite factory per garantire configurazione corretta:
|
||||
```csharp
|
||||
var dbManager = await ConnectionFactory.CreateDatabaseManagerAsync(credentialName);
|
||||
var restClient = await ConnectionFactory.CreateRestServiceClientAsync(credentialName);
|
||||
```
|
||||
|
||||
#### Service Layer
|
||||
La logica business è incapsulata in servizi dedicati:
|
||||
- `CredentialService`: Gestione credenziali
|
||||
- `DataCouplerProfileService`: Gestione profili
|
||||
- `DataConnectionFactory`: Creazione connessioni
|
||||
|
||||
---
|
||||
|
||||
## Stato delle Implementazioni
|
||||
|
||||
### ✅ Funzionalità Completamente Implementate
|
||||
|
||||
#### Gestione Credenziali
|
||||
- ✅ Salvataggio/recupero credenziali database
|
||||
- ✅ Salvataggio/recupero credenziali REST API
|
||||
- ✅ Crittografia cross-platform
|
||||
- ✅ Test connessioni
|
||||
- ✅ Validazione credenziali
|
||||
|
||||
#### Connessioni Database
|
||||
- ✅ Supporto multi-database (SQL Server, MySQL, PostgreSQL, etc.)
|
||||
- ✅ Schema discovery automatico
|
||||
- ✅ Query personalizzate
|
||||
- ✅ Gestione connection string
|
||||
|
||||
#### Connessioni REST
|
||||
- ✅ API generiche
|
||||
- ✅ Integrazione Salesforce completa
|
||||
- ✅ Salesforce Composite API per performance
|
||||
- ✅ Autenticazione OAuth
|
||||
|
||||
#### Elaborazione File
|
||||
- ✅ Lettura Excel (.xlsx, .xls)
|
||||
- ✅ Lettura CSV
|
||||
- ✅ Preview dati con paginazione
|
||||
- ✅ Gestione multi-sheet
|
||||
|
||||
#### Sistema Mapping
|
||||
- ✅ Mapping manuale campi
|
||||
- ✅ Auto-detection campi simili
|
||||
- ✅ Validazione mapping
|
||||
- ✅ Preview risultati
|
||||
|
||||
#### Gestione Associazioni
|
||||
- ✅ Tracking chiavi sorgente-destinazione
|
||||
- ✅ Prevenzione duplicati
|
||||
- ✅ Hash verification per rilevare modifiche
|
||||
- ✅ Gestione update vs insert intelligente
|
||||
|
||||
#### Gestione Profili
|
||||
- ✅ Salvataggio configurazioni complete
|
||||
- ✅ Caricamento profili salvati
|
||||
- ✅ Lista e gestione profili
|
||||
- ✅ Statistiche utilizzo
|
||||
- ✅ Export/import JSON
|
||||
|
||||
### 🔄 Funzionalità Parzialmente Implementate
|
||||
|
||||
#### Background Services
|
||||
- 🔄 **Struttura base**: Implementata ma placeholder
|
||||
- 🔄 **Servizi specifici**: Da implementare funzionalità specifiche
|
||||
- 🔄 **Scheduling**: Da aggiungere scheduling operazioni
|
||||
|
||||
#### Gestione Errori Avanzata
|
||||
- 🔄 **Logging base**: Implementato
|
||||
- 🔄 **Error recovery**: Parziale
|
||||
- 🔄 **Rollback automatico**: Da implementare
|
||||
|
||||
#### Performance Optimization
|
||||
- 🔄 **Batch processing**: Implementato per Salesforce
|
||||
- 🔄 **Parallelizzazione**: Parziale
|
||||
- 🔄 **Caching**: Base implementato
|
||||
|
||||
#### Security Features
|
||||
- 🔄 **Autenticazione utente**: Da implementare
|
||||
- 🔄 **Autorizzazione**: Da implementare
|
||||
- 🔄 **Audit trail**: Parziale
|
||||
|
||||
### ❌ Funzionalità Da Implementare
|
||||
|
||||
#### Integrazione Database Avanzata
|
||||
- ❌ **Supporto Stored Procedures**: Da implementare
|
||||
- ❌ **Triggers**: Da implementare
|
||||
- ❌ **Views materialized**: Da implementare
|
||||
|
||||
#### API Extensions
|
||||
- ❌ **GraphQL**: Da implementare
|
||||
- ❌ **SAP B1 Service Layer completo**: Struttura presente ma da completare
|
||||
- ❌ **Altri ERP**: Da aggiungere
|
||||
|
||||
#### Data Transformation
|
||||
- ❌ **Trasformazioni custom**: Da implementare
|
||||
- ❌ **Formule/Calcoli**: Da implementare
|
||||
- ❌ **Data cleansing**: Da implementare
|
||||
|
||||
#### Monitoring & Analytics
|
||||
- ❌ **Dashboard performance**: Da implementare
|
||||
- ❌ **Metriche dettagliate**: Da implementare
|
||||
- ❌ **Alerting**: Da implementare
|
||||
|
||||
#### Advanced Features
|
||||
- ❌ **Real-time sync**: Da implementare
|
||||
- ❌ **Conflict resolution**: Da implementare
|
||||
- ❌ **Multi-tenant**: Da implementare
|
||||
- ❌ **REST API del Data Coupler**: Da implementare
|
||||
|
||||
---
|
||||
|
||||
## Utilizzo e Configurazione
|
||||
|
||||
### Configurazione Iniziale
|
||||
|
||||
1. **Compilazione e Avvio**:
|
||||
```bash
|
||||
dotnet run --project Data_Coupler/Data_Coupler.csproj
|
||||
```
|
||||
|
||||
2. **Accesso Web Interface**:
|
||||
- URL: `http://localhost:7550`
|
||||
- L'applicazione inizializza automaticamente il database SQLite
|
||||
|
||||
### Workflow Tipico
|
||||
|
||||
#### 1. Configurazione Credenziali
|
||||
- Accedere alla sezione "Gestione Credenziali"
|
||||
- Aggiungere credenziali database e/o REST API
|
||||
- Testare le connessioni
|
||||
|
||||
#### 2. Configurazione Trasferimento
|
||||
- Selezionare tipo sorgente (Database/File)
|
||||
- Configurare connessione sorgente
|
||||
- Configurare destinazione REST API
|
||||
- Definire mapping campi
|
||||
- Configurare gestione chiavi
|
||||
|
||||
#### 3. Esecuzione Trasferimento
|
||||
- Avviare trasferimento dati
|
||||
- Monitorare progresso
|
||||
- Verificare risultati
|
||||
|
||||
#### 4. Gestione Profili (Opzionale)
|
||||
- Salvare configurazione come profilo
|
||||
- Riutilizzare profili per operazioni ricorrenti
|
||||
|
||||
### Configurazioni Avanzate
|
||||
|
||||
#### Database Path Personalizzato
|
||||
Modificare `Program.cs` per percorso custom:
|
||||
```csharp
|
||||
string customDbPath = "/path/to/custom/credentials.db";
|
||||
builder.Services.AddDataConnectionCredentialManagement($"Data Source={customDbPath}");
|
||||
```
|
||||
|
||||
#### Logging Personalizzato
|
||||
Configurare logging in `Program.cs`:
|
||||
```csharp
|
||||
builder.Logging.AddConsole();
|
||||
builder.Logging.SetMinimumLevel(LogLevel.Debug);
|
||||
```
|
||||
|
||||
#### Performance Tuning
|
||||
- **Batch Size**: Configurabile nel codice per operazioni batch
|
||||
- **Timeout**: Configurabile per connessioni database/REST
|
||||
- **Memory**: Gestione automatica, configurabile per file grandi
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### Problemi Comuni
|
||||
1. **Database Lock**: Riavviare applicazione
|
||||
2. **Credenziali non funzionanti**: Verificare test connessione
|
||||
3. **File non leggibili**: Verificare formato e permissions
|
||||
4. **API Rate Limiting**: Configurare delays appropriati
|
||||
|
||||
#### Log Files
|
||||
I log sono disponibili nella console dell'applicazione e possono essere configurati per output su file.
|
||||
|
||||
---
|
||||
|
||||
## Conclusioni
|
||||
|
||||
Data-Coupler rappresenta una soluzione robusta e flessibile per l'integrazione di dati tra diverse piattaforme. L'architettura modulare consente estensioni future, mentre le funzionalità già implementate coprono la maggior parte dei casi d'uso comuni.
|
||||
|
||||
Il progetto è in uno stato maturo per quanto riguarda le funzionalità core, con spazio per miglioramenti in aree come monitoring, security avanzata e funzionalità enterprise.
|
||||
|
||||
### Prossimi Sviluppi Consigliati
|
||||
1. Implementazione sistema di autenticazione utenti
|
||||
2. Dashboard analytics e monitoring
|
||||
3. API REST per automazione
|
||||
4. Supporto trasformazioni dati avanzate
|
||||
5. Integrazione con sistemi di workflow
|
||||
|
||||
---
|
||||
|
||||
**Versione Documentazione**: 1.0
|
||||
**Data**: 11 Settembre 2025
|
||||
**Autore**: Sistema di Documentazione Automatica Data-Coupler
|
||||
Reference in New Issue
Block a user