feat: Implementato sistema di associazioni chiave per prevenire duplicati nel data coupling
BREAKING CHANGE: Rimosso completamente il vecchio sistema RecordAssociation Modifiche principali: - Sostituito RecordAssociation con KeyAssociation basato sui valori delle chiavi - Implementata logica robusta di UPDATE vs INSERT basata su associazioni esistenti - Aggiunta normalizzazione delle chiavi (.Trim()) per consistenza - Implementato fallback nella ricerca associazioni per maggiore affidabilità - Sostituita verifica pre-UPDATE con tentativo diretto più efficiente Componenti modificati: - Nuovo modello: KeyAssociation.cs con campi ottimizzati - Nuovo servizio: KeyAssociationService.cs con metodi completi - Aggiornato: DataCoupler.razor con logica migliorata di gestione associazioni - Aggiornato: CredentialDbContext per gestire solo KeyAssociations - Aggiornati: tutti i servizi di interfaccia per supportare il nuovo sistema - Creata: pagina KeyAssociations.razor per gestione associazioni - Aggiornato: NavMenu.razor con link alla gestione associazioni Miglioramenti tecnici: - Logica di UPDATE più robusta: tenta direttamente l'aggiornamento invece di verificare prima l'esistenza - Gestione errori migliorata con cleanup automatico delle associazioni non valide - Debug logging estensivo per troubleshooting - Fallback nella ricerca associazioni se parametri specifici falliscono - Normalizzazione valori chiave per prevenire problemi di whitespace Risultato: Il sistema ora previene correttamente i duplicati utilizzando le associazioni per decidere se fare INSERT (nuovo record) o UPDATE (record esistente) basandosi sui valori delle chiavi. Database: - Creata migrazione EF per rimuovere RecordAssociations e aggiungere KeyAssociations - Eliminati file e codice legacy non più necessari
This commit is contained in:
+17
-13
@@ -1,4 +1,5 @@
|
||||
using CredentialManager.Models;
|
||||
using CredentialManager.Services;
|
||||
|
||||
namespace DataConnection.CredentialManagement.Interfaces;
|
||||
|
||||
@@ -57,17 +58,20 @@ public interface IDataConnectionCredentialService
|
||||
Task<(bool Success, string Message)> TestSalesforceConnectionAsync(string credentialName);
|
||||
Task<(bool Success, string Message)> TestSalesforceConnectionAsync(SalesforceCredential credential);
|
||||
|
||||
// Record associations
|
||||
Task<int> SaveRecordAssociationAsync(RecordAssociation association);
|
||||
Task<RecordAssociation?> FindRecordAssociationAsync(string sourceName, string sourceKey, string destinationEntity);
|
||||
Task<List<RecordAssociation>> GetRecordAssociationsBySourceAsync(string sourceName, string sourceType);
|
||||
Task<List<RecordAssociation>> GetRecordAssociationsByDestinationAsync(string destinationEntity, string restCredentialName);
|
||||
Task<List<RecordAssociation>> GetAllActiveRecordAssociationsAsync();
|
||||
Task<bool> UpdateRecordAssociationAsync(RecordAssociation association);
|
||||
Task<bool> DeactivateRecordAssociationAsync(int id);
|
||||
Task<bool> DeleteRecordAssociationAsync(int id);
|
||||
Task<int> ClearRecordAssociationsAsync(string sourceName, string destinationEntity, string restCredentialName);
|
||||
Task<int> ClearAllRecordAssociationsAsync();
|
||||
Task<List<RecordAssociation>> GetInvalidRecordAssociationsAsync(string destinationEntity, string restCredentialName);
|
||||
Task<int> CleanupInvalidRecordAssociationsAsync(string destinationEntity, string restCredentialName);
|
||||
// Key associations
|
||||
Task<int> SaveKeyAssociationAsync(KeyAssociation association);
|
||||
Task<KeyAssociation?> FindKeyAssociationByValueAsync(string keyValue, string destinationEntity, string restCredentialName);
|
||||
Task<KeyAssociation?> FindKeyAssociationByValueAsync(string keyValue);
|
||||
Task<List<KeyAssociation>> GetKeyAssociationsByDestinationAsync(string destinationEntity, string restCredentialName);
|
||||
Task<List<KeyAssociation>> GetAllActiveKeyAssociationsAsync();
|
||||
Task<List<KeyAssociation>> GetAllKeyAssociationsAsync();
|
||||
Task<bool> UpdateKeyAssociationAsync(KeyAssociation association);
|
||||
Task<bool> DeactivateKeyAssociationAsync(int id);
|
||||
Task<bool> DeleteKeyAssociationAsync(int id);
|
||||
Task<int> ClearKeyAssociationsAsync(string destinationEntity, string restCredentialName);
|
||||
Task<int> ClearAllKeyAssociationsAsync();
|
||||
Task<List<KeyAssociation>> GetInvalidKeyAssociationsAsync(string destinationEntity, string restCredentialName);
|
||||
Task<int> CleanupInvalidKeyAssociationsAsync(string destinationEntity, string restCredentialName);
|
||||
Task<bool> UpdateKeyAssociationLastVerifiedAsync(int id);
|
||||
Task<AssociationStatistics> GetKeyAssociationStatisticsAsync();
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ public static class ServiceCollectionExtensions
|
||||
// Aggiungi i servizi base di CredentialManager
|
||||
services.AddCredentialManager(databasePath);
|
||||
|
||||
// Aggiungi il servizio di gestione associazioni record
|
||||
services.AddScoped<IRecordAssociationService, RecordAssociationService>();
|
||||
// Aggiungi il servizio di gestione associazioni per chiavi
|
||||
services.AddScoped<IKeyAssociationService, KeyAssociationService>();
|
||||
|
||||
// Aggiungi il servizio di integrazione DataConnection
|
||||
services.AddScoped<IDataConnectionCredentialService, DataConnectionCredentialService>();
|
||||
|
||||
@@ -15,16 +15,16 @@ namespace DataConnection.CredentialManagement.Services;
|
||||
public class DataConnectionCredentialService : IDataConnectionCredentialService
|
||||
{
|
||||
private readonly ICredentialService _credentialService;
|
||||
private readonly IRecordAssociationService _recordAssociationService;
|
||||
private readonly IKeyAssociationService _keyAssociationService;
|
||||
private readonly ILogger<DataConnectionCredentialService> _logger;
|
||||
|
||||
public DataConnectionCredentialService(
|
||||
ICredentialService credentialService,
|
||||
IRecordAssociationService recordAssociationService,
|
||||
IKeyAssociationService keyAssociationService,
|
||||
ILogger<DataConnectionCredentialService> logger)
|
||||
{
|
||||
_credentialService = credentialService;
|
||||
_recordAssociationService = recordAssociationService;
|
||||
_keyAssociationService = keyAssociationService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -859,66 +859,81 @@ public class DataConnectionCredentialService : IDataConnectionCredentialService
|
||||
|
||||
#endregion
|
||||
|
||||
#region Record Associations
|
||||
#region Key Associations
|
||||
|
||||
public async Task<int> SaveRecordAssociationAsync(RecordAssociation association)
|
||||
public async Task<int> SaveKeyAssociationAsync(KeyAssociation association)
|
||||
{
|
||||
return await _recordAssociationService.SaveAssociationAsync(association);
|
||||
return await _keyAssociationService.SaveAssociationAsync(association);
|
||||
}
|
||||
|
||||
public async Task<RecordAssociation?> FindRecordAssociationAsync(string sourceName, string sourceKey, string destinationEntity)
|
||||
public async Task<KeyAssociation?> FindKeyAssociationByValueAsync(string keyValue, string destinationEntity, string restCredentialName)
|
||||
{
|
||||
return await _recordAssociationService.FindAssociationAsync(sourceName, sourceKey, destinationEntity);
|
||||
return await _keyAssociationService.FindAssociationByKeyValueAsync(keyValue, destinationEntity, restCredentialName);
|
||||
}
|
||||
|
||||
public async Task<List<RecordAssociation>> GetRecordAssociationsBySourceAsync(string sourceName, string sourceType)
|
||||
public async Task<KeyAssociation?> FindKeyAssociationByValueAsync(string keyValue)
|
||||
{
|
||||
return await _recordAssociationService.GetAssociationsBySourceAsync(sourceName, sourceType);
|
||||
return await _keyAssociationService.FindAssociationByKeyValueAsync(keyValue);
|
||||
}
|
||||
|
||||
public async Task<List<RecordAssociation>> GetRecordAssociationsByDestinationAsync(string destinationEntity, string restCredentialName)
|
||||
public async Task<List<KeyAssociation>> GetKeyAssociationsByDestinationAsync(string destinationEntity, string restCredentialName)
|
||||
{
|
||||
return await _recordAssociationService.GetAssociationsByDestinationAsync(destinationEntity, restCredentialName);
|
||||
return await _keyAssociationService.GetAssociationsByDestinationAsync(destinationEntity, restCredentialName);
|
||||
}
|
||||
|
||||
public async Task<List<RecordAssociation>> GetAllActiveRecordAssociationsAsync()
|
||||
public async Task<List<KeyAssociation>> GetAllActiveKeyAssociationsAsync()
|
||||
{
|
||||
return await _recordAssociationService.GetAllActiveAssociationsAsync();
|
||||
return await _keyAssociationService.GetAllActiveAssociationsAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateRecordAssociationAsync(RecordAssociation association)
|
||||
public async Task<List<KeyAssociation>> GetAllKeyAssociationsAsync()
|
||||
{
|
||||
return await _recordAssociationService.UpdateAssociationAsync(association);
|
||||
return await _keyAssociationService.GetAllAssociationsAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> DeactivateRecordAssociationAsync(int id)
|
||||
public async Task<bool> UpdateKeyAssociationAsync(KeyAssociation association)
|
||||
{
|
||||
return await _recordAssociationService.DeactivateAssociationAsync(id);
|
||||
return await _keyAssociationService.UpdateAssociationAsync(association);
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteRecordAssociationAsync(int id)
|
||||
public async Task<bool> DeactivateKeyAssociationAsync(int id)
|
||||
{
|
||||
return await _recordAssociationService.DeleteAssociationAsync(id);
|
||||
return await _keyAssociationService.DeactivateAssociationAsync(id);
|
||||
}
|
||||
|
||||
public async Task<int> ClearRecordAssociationsAsync(string sourceName, string destinationEntity, string restCredentialName)
|
||||
public async Task<bool> DeleteKeyAssociationAsync(int id)
|
||||
{
|
||||
return await _recordAssociationService.ClearAssociationsAsync(sourceName, destinationEntity, restCredentialName);
|
||||
return await _keyAssociationService.DeleteAssociationAsync(id);
|
||||
}
|
||||
|
||||
public async Task<int> ClearAllRecordAssociationsAsync()
|
||||
public async Task<int> ClearKeyAssociationsAsync(string destinationEntity, string restCredentialName)
|
||||
{
|
||||
return await _recordAssociationService.ClearAllAssociationsAsync();
|
||||
return await _keyAssociationService.ClearAssociationsAsync(destinationEntity, restCredentialName);
|
||||
}
|
||||
|
||||
public async Task<List<RecordAssociation>> GetInvalidRecordAssociationsAsync(string destinationEntity, string restCredentialName)
|
||||
public async Task<int> ClearAllKeyAssociationsAsync()
|
||||
{
|
||||
return await _recordAssociationService.GetInvalidAssociationsAsync(destinationEntity, restCredentialName);
|
||||
return await _keyAssociationService.ClearAllAssociationsAsync();
|
||||
}
|
||||
|
||||
public async Task<int> CleanupInvalidRecordAssociationsAsync(string destinationEntity, string restCredentialName)
|
||||
public async Task<List<KeyAssociation>> GetInvalidKeyAssociationsAsync(string destinationEntity, string restCredentialName)
|
||||
{
|
||||
return await _recordAssociationService.CleanupInvalidAssociationsAsync(destinationEntity, restCredentialName);
|
||||
return await _keyAssociationService.GetInvalidAssociationsAsync(destinationEntity, restCredentialName);
|
||||
}
|
||||
|
||||
public async Task<int> CleanupInvalidKeyAssociationsAsync(string destinationEntity, string restCredentialName)
|
||||
{
|
||||
return await _keyAssociationService.CleanupInvalidAssociationsAsync(destinationEntity, restCredentialName);
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateKeyAssociationLastVerifiedAsync(int id)
|
||||
{
|
||||
return await _keyAssociationService.UpdateLastVerifiedAsync(id);
|
||||
}
|
||||
|
||||
public async Task<AssociationStatistics> GetKeyAssociationStatisticsAsync()
|
||||
{
|
||||
return await _keyAssociationService.GetStatisticsAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user