@page "/data-coupler" @using CredentialManager.Models @using DataConnection.Interfaces @using DataConnection.CredentialManagement.Interfaces @using DataConnection.REST.Interfaces @using DataConnection.REST.Models @using Data_Coupler.Services @using Microsoft.AspNetCore.Components.Forms @using Microsoft.JSInterop @using System.IO @using System.Text @using System.Data @using ExcelDataReader @inject IDataConnectionCredentialService CredentialService @inject IDataConnectionFactory ConnectionFactory @inject IJSRuntime JSRuntime @inject ILogger Logger Data Coupler

Data Coupler - Coupling Database e REST API

Connetti database e servizi REST per il trasferimento dati

Fonte Dati
@if (selectedSourceType == "database") {
@if (!string.IsNullOrEmpty(selectedDatabaseCredential)) {
@if (isDatabaseConnected) { Connesso }
} @if (!string.IsNullOrEmpty(databaseErrorMessage)) { } @if (isDatabaseConnected) {
Scegli se selezionare una tabella o scrivere una query SQL personalizzata
@if (useCustomQuery) {
Query SQL Custom:
@if (isQueryValid) { @if (showQueryPreview) { } }
@if (!string.IsNullOrEmpty(queryValidationMessage) && !isQueryValid) { } @if (showQueryPreview && queryPreviewData.Any()) {
Anteprima Risultati Query @queryPreviewData.Count righe
@if (queryColumns.Any()) { @foreach (var column in queryColumns) { } } @foreach (var row in queryPreviewData.Take(20)) { @foreach (var column in queryColumns) { } }
@column
@(row.ContainsKey(column) ? row[column]?.ToString() ?? "" : "")
@if (queryPreviewData.Count > 20) { }
}
} else if (databaseTables.Any()) {
Tabelle Database (@databaseTables.Count disponibili):
@if (!string.IsNullOrEmpty(databaseSearchTerm)) { }
@if (!GetFilteredDatabaseTables().Any()) {
Nessuna tabella trovata con il termine di ricerca "@databaseSearchTerm"
}
} } } @if (selectedSourceType == "file") {
@if (!string.IsNullOrEmpty(selectedFileName)) { File selezionato: @selectedFileName }
@if (isProcessingFile) {
Elaborazione file in corso...
} @if (!string.IsNullOrEmpty(fileErrorMessage)) { } @if (fileSheets.Any()) {
@{ var fileExtension = Path.GetExtension(selectedFileName).ToLowerInvariant(); var isExcel = fileExtension == ".xlsx" || fileExtension == ".xls"; var fileTypeIcon = isExcel ? "fa-file-excel text-success" : "fa-file-csv text-info"; var fileTypeName = isExcel ? "Excel" : "CSV"; }
Fogli @fileTypeName (@fileSheets.Count):
} else if (selectedSourceType == "file" && !string.IsNullOrEmpty(selectedFileName) && !isProcessingFile && string.IsNullOrEmpty(fileErrorMessage)) { } else if (selectedSourceType == "file" && string.IsNullOrEmpty(selectedFileName)) { } @if (!string.IsNullOrEmpty(selectedSheet) && fileData.ContainsKey(selectedSheet) && fileData[selectedSheet].Any()) {
Preview Dati - @selectedSheet
Record @GetStartRecord()-@GetEndRecord() di @fileData[selectedSheet].Count
@currentPage di @GetTotalPages(selectedSheet)
@if (fileSheets.ContainsKey(selectedSheet)) {
@foreach (var column in fileSheets[selectedSheet]) { } @{ var dataToShow = GetCurrentPageData(); var startRecord = GetStartRecord(); } @for (int i = 0; i < dataToShow.Count; i++) { var row = dataToShow[i]; var absoluteRowIndex = startRecord + i; @foreach (var column in fileSheets[selectedSheet]) { var cellValue = row.ContainsKey(column) ? row[column]?.ToString() : ""; var displayValue = string.IsNullOrEmpty(cellValue) ? "-" : (cellValue.Length > 50 ? cellValue.Substring(0, 50) + "..." : cellValue); } }
#@column
@absoluteRowIndex @displayValue
}
} }
REST API Destination
@if (!string.IsNullOrEmpty(selectedRestCredential)) {
@if (isRestConnected) { Connesso }
} @if (!string.IsNullOrEmpty(restErrorMessage)) { } @if (restEntities.Any()) {
Entità REST (@restEntities.Count disponibili):
@if (!string.IsNullOrEmpty(restSearchTerm)) { }
@if (!GetFilteredRestEntities().Any()) {
Nessuna entità trovata con il termine di ricerca "@restSearchTerm"
}
}
@{ var isSourceReady = (selectedSourceType == "database" && isDatabaseConnected && ((useCustomQuery && isQueryValid) || (!useCustomQuery && !string.IsNullOrEmpty(selectedTable)))) || (selectedSourceType == "file" && !string.IsNullOrEmpty(selectedSheet)); } @if (isSourceReady && isRestConnected && selectedRestEntity != null) {
Mapping Campi
@{ var sourceDisplayName = selectedSourceType == "database" ? selectedTable : selectedSheet; var sourceTypeName = selectedSourceType == "database" ? "Tabella" : "Foglio"; }
Mapping tra @sourceTypeName @sourceDisplayName e @selectedRestEntity.Name

Configura il mapping tra i campi della fonte dati e le proprietà dell'entità REST

Campi @sourceTypeName (@sourceDisplayName)
@if (selectedSourceType == "database" && useCustomQuery && queryColumns.Any()) { }
@if (selectedSourceType == "database") { @if (useCustomQuery && queryColumns.Any()) { @foreach (var column in queryColumns) {
@column Query Column
@if (fieldMappings.ContainsKey(column)) { Mapped }
} } else if (!useCustomQuery && databaseTables.ContainsKey(selectedTable)) { @foreach (var column in databaseTables[selectedTable]) {
@column.Name @column.DataType
@if (column.IsPrimaryKey) { PK } @if (fieldMappings.ContainsKey(column.Name)) { Mapped }
} } } else if (selectedSourceType == "file" && fileSheets.ContainsKey(selectedSheet)) { @foreach (var column in fileSheets[selectedSheet]) {
@column Colonna File
@if (fieldMappings.ContainsKey(column)) { Mapped }
} }
Proprietà REST (@selectedRestEntity.Name)
@if (restEntityDetails != null) { @foreach (var property in restEntityDetails.Properties) {
@property.Name @property.Type
@if (property.IsRequired) { Required } @if (fieldMappings.ContainsValue(property.Name)) { Mapped }
} }
@if (fieldMappings.Any()) {
Mappature Correnti (@fieldMappings.Count)
@if (keyFields.Any()) { @keyFields.Count campo/i chiave: @string.Join(", ", keyFields) }
@foreach (var mapping in fieldMappings) { DbColumnInfo? dbColumn = null; if (selectedSourceType == "database" && !string.IsNullOrEmpty(selectedTable)) { dbColumn = databaseTables.ContainsKey(selectedTable) ? databaseTables[selectedTable].FirstOrDefault(c => c.Name == mapping.Key) : null; } var restProperty = restEntityDetails?.Properties.FirstOrDefault(p => p.Name == mapping.Value); }
Campo Database Tipo DB Proprietà REST Tipo REST Azioni
@mapping.Key @(dbColumn?.DataType ?? (selectedSourceType == "file" ? "Text" : "Unknown")) @mapping.Value @(restProperty?.Type ?? "Unknown")
} @if (fieldMappings.Any()) {
Configurazione Chiave Sorgente
@if (useRecordAssociations) {
Come funziona il nuovo sistema:
  • Ogni valore di chiave univoco viene associato a un record di destinazione
  • Più sorgenti diverse possono gestire lo stesso oggetto business usando lo stesso valore chiave
  • Gli aggiornamenti avvengono automaticamente quando si trova un'associazione esistente
  • Il sistema individua automaticamente le chiavi dove possibile, ma puoi sempre scegliere manualmente
@if (requiresManualKeySelection || selectedSourceType != "database") { Selezione del campo chiave obbligatoria. Scegli un campo che identifichi univocamente ogni record. } else if (!string.IsNullOrEmpty(suggestedPrimaryKey)) { Primary Key rilevata: @suggestedPrimaryKey (consigliato per l'identificazione univoca) }
@if (!string.IsNullOrEmpty(sourceKeyField)) {
Campo chiave selezionato: @sourceKeyField
Questo campo verrà utilizzato per identificare univocamente i record sorgente @if (sourceKeyField == suggestedPrimaryKey) {
Ottima scelta! Stai usando la Primary Key della tabella. }
} else {
Campo chiave richiesto
Seleziona un campo che identifichi univocamente ogni record per abilitare il sistema di associazioni. @if (!string.IsNullOrEmpty(suggestedPrimaryKey)) {
Consiglio: seleziona @suggestedPrimaryKey (Primary Key rilevata) }
}
} else {
Sistema associazioni disabilitato
Tutti i record verranno sempre inseriti come nuovi. Non sarà possibile tracciare aggiornamenti automatici.
}
}
@if (fieldMappings.Any()) { }
@if (fieldMappings.Any()) { @fieldMappings.Count mapping(s) configurati
@if (useRecordAssociations) { Modalità Smart Update @if (!string.IsNullOrEmpty(sourceKeyField)) { (Chiave: @sourceKeyField) } else { (Rilevamento automatico) } } else { Modalità Insert Only }
} else { Configura almeno una mappatura per iniziare }
@if (!string.IsNullOrEmpty(transferMessage)) { } @if (transferResults.Any()) {
Risultati Dettagliati Trasferimento (@transferResults.Count record)
Inseriti: @transferResults.Count(r => r.Status == "success")
Aggiornati: @transferResults.Count(r => r.Status == "updated")
Duplicati: @transferResults.Count(r => r.Status == "duplicate")
Errori: @transferResults.Count(r => r.Status == "error")
@foreach (var result in transferResults) { }
# Stato ID Entità Messaggio
@result.RecordNumber @GetResultStatusText(result.Status) @if (!string.IsNullOrEmpty(result.EntityId)) { @result.EntityId } else { - } @result.Message
}
}
@if (showDatabaseSelectionModal) { }