04f0403f12
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
110 lines
3.7 KiB
C#
110 lines
3.7 KiB
C#
using CredentialManager.Models;
|
|
|
|
namespace CredentialManager.Services;
|
|
|
|
/// <summary>
|
|
/// Interfaccia per il servizio di gestione delle associazioni basate sui valori delle chiavi
|
|
/// </summary>
|
|
public interface IKeyAssociationService
|
|
{
|
|
/// <summary>
|
|
/// Salva una nuova associazione o aggiorna una esistente
|
|
/// </summary>
|
|
Task<int> SaveAssociationAsync(KeyAssociation association);
|
|
|
|
/// <summary>
|
|
/// Cerca un'associazione esistente tramite valore chiave
|
|
/// </summary>
|
|
Task<KeyAssociation?> FindAssociationByKeyValueAsync(string keyValue, string destinationEntity, string restCredentialName);
|
|
|
|
/// <summary>
|
|
/// Cerca un'associazione esistente tramite valore chiave, indipendentemente dalla destinazione
|
|
/// </summary>
|
|
Task<KeyAssociation?> FindAssociationByKeyValueAsync(string keyValue);
|
|
|
|
/// <summary>
|
|
/// Ottiene tutte le associazioni per un'entità di destinazione specifica
|
|
/// </summary>
|
|
Task<List<KeyAssociation>> GetAssociationsByDestinationAsync(string destinationEntity, string restCredentialName);
|
|
|
|
/// <summary>
|
|
/// Ottiene tutte le associazioni attive
|
|
/// </summary>
|
|
Task<List<KeyAssociation>> GetAllActiveAssociationsAsync();
|
|
|
|
/// <summary>
|
|
/// Ottiene tutte le associazioni (attive e non)
|
|
/// </summary>
|
|
Task<List<KeyAssociation>> GetAllAssociationsAsync();
|
|
|
|
/// <summary>
|
|
/// Aggiorna un'associazione esistente
|
|
/// </summary>
|
|
Task<bool> UpdateAssociationAsync(KeyAssociation association);
|
|
|
|
/// <summary>
|
|
/// Disattiva un'associazione
|
|
/// </summary>
|
|
Task<bool> DeactivateAssociationAsync(int id);
|
|
|
|
/// <summary>
|
|
/// Elimina definitivamente un'associazione
|
|
/// </summary>
|
|
Task<bool> DeleteAssociationAsync(int id);
|
|
|
|
/// <summary>
|
|
/// Pulisce le associazioni più vecchie di un determinato periodo
|
|
/// </summary>
|
|
Task<int> CleanupOldAssociationsAsync(TimeSpan olderThan);
|
|
|
|
/// <summary>
|
|
/// Elimina tutte le associazioni per una specifica combinazione entità-credenziale
|
|
/// </summary>
|
|
Task<int> ClearAssociationsAsync(string destinationEntity, string restCredentialName);
|
|
|
|
/// <summary>
|
|
/// Elimina tutte le associazioni nel sistema
|
|
/// </summary>
|
|
Task<int> ClearAllAssociationsAsync();
|
|
|
|
/// <summary>
|
|
/// Verifica se un ID di destinazione esiste ancora nel sistema target
|
|
/// </summary>
|
|
Task<bool> ValidateDestinationIdAsync(string destinationId, string destinationEntity, string restCredentialName);
|
|
|
|
/// <summary>
|
|
/// Ottiene tutte le associazioni con ID di destinazione non validi
|
|
/// </summary>
|
|
Task<List<KeyAssociation>> GetInvalidAssociationsAsync(string destinationEntity, string restCredentialName);
|
|
|
|
/// <summary>
|
|
/// Pulisce le associazioni con ID di destinazione non più validi
|
|
/// </summary>
|
|
Task<int> CleanupInvalidAssociationsAsync(string destinationEntity, string restCredentialName);
|
|
|
|
/// <summary>
|
|
/// Aggiorna la data di ultima verifica per un'associazione
|
|
/// </summary>
|
|
Task<bool> UpdateLastVerifiedAsync(int id);
|
|
|
|
/// <summary>
|
|
/// Ottiene statistiche sulle associazioni
|
|
/// </summary>
|
|
Task<AssociationStatistics> GetStatisticsAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Statistiche sulle associazioni
|
|
/// </summary>
|
|
public class AssociationStatistics
|
|
{
|
|
public int TotalAssociations { get; set; }
|
|
public int ActiveAssociations { get; set; }
|
|
public int InactiveAssociations { get; set; }
|
|
public int UniqueKeyValues { get; set; }
|
|
public int UniqueDestinationEntities { get; set; }
|
|
public DateTime? OldestAssociation { get; set; }
|
|
public DateTime? NewestAssociation { get; set; }
|
|
public Dictionary<string, int> AssociationsByEntity { get; set; } = new();
|
|
}
|