Gestione tabelle dati aggiuntivi non legati da foreign key

Alle volte capita di dover interagire con un database nato molti anni addietro e di non poterlo modificare in quanto utilizzato da diversi applicativi e quindi occorre adattare il proprio codice per ricondurlo ad un caso semplice dal quale realizzare un pannello in una videata.

Il caso è questo:

  • tabella Clienti (pk CodiceCliente - 6A)
  • tabella Fornitori (pk CodiceFornitore - 6A)
  • tabella AnagraficheAggiuntive (pk Progressivo - autoincrement)

La tabella AnagraficheAggiuntive contiene dati aggiuntivi che possono essere sia della tabella Clienti che della tabella Fornitori; a differenziarli è presente il campo TipoAnagrafica (CL/FO).
Nella tabella AnagraficheAggiuntive è presente il campo CodiceAnagrafica che può contenere un valore del campo CodiceFornitore o del campo CodiceCliente (quindi non è possibile creare una fk verso le due tabelle Clienti e Fornitori).

Come lo posso gestire, su Instant Developer Foundation, facendo in modo che i campi della tabella AnagraficheAggiuntive li veda nei documenti Cliente e Fornitore come fossero della stessa tabella?

Naturalmente nel nostro progetto di Foundation abbiamo un componente con al suo interno i documenti delle tre tabelle. Quindi nei documenti Cliente e Fornitore aggiungiamo i campi della tabella AnagraficheAggiuntive come proprietà aggiuntive.

Analizziamo le modifiche da apportare al documento Cliente e poi analogamente le faremo anche sul documento Fornitore.

Aggiungiamo una query al documento per caricare con un outer join i dati della tabella AnagraficheAggiuntive:

select
  set CodiceCliente = Clienti.CodiceCliente
  set RagioneSociale = Clienti.RagioneSociale
  set PartitaIVA = Clienti.PartitaIVA
  set CondizioniPagamento = Clienti.CondizioniPagamento
  set Descrizione = AnagraficheAggiuntive.Descrizione
  set Email = AnagraficheAggiuntive.Email
  set Vettore = AnagraficheAggiuntive.Vettore
  set TipoAnagrafica = AnagraficheAggiuntive.TipoAnagrafica
from 
  Clienti                          // master table
  outer join AnagraficheAggiuntive // manually joined, see where clauses
where
  AnagraficheAggiuntive.TipoAnagrafica = Cliente
  AnagraficheAggiuntive.CodiceAnagrafica* = Clienti.CodiceCliente

Nella query è anche indicata la selezione dei soli record di tipo cliente della tabella AnagraficheAggiuntive.

Nell’evento OnInit del documento Cliente andremo ad impostare il campo:

TipoAnagrafica = Cliente

Ora viene la parte più interessante, l’evento BeforeSave del documento Cliente:

// Inserimento
if (Phase == 1 && inserted)
{
  AnagraficaAggiuntiva aa = new()
  aa.init()
  this.ImpostaCampiAnagraficaAggiuntiva(aa)
   
  if (!(aa.saveToDB(...)))
  {
    string errorMessage = Utility.recuperaErrori(aa)
    this.addDocumentError(errorMessage)
  }
}
 
// Modifica
if (Phase == 2 && updated)
{
  AnagraficaAggiuntiva aa = new()
  aa.CodiceAnagrafica = CodiceCliente
   
  try 
  {
    aa.loadFromDB(...)
    this.ImpostaCampiAnagraficaAggiuntiva(aa)
     
    if (!(aa.saveToDB(...)))
    {
       string errorMessage = Utility.recuperaErrori(aa)
       this.addDocumentError(errorMessage)
    }
  }
  catch  // Anagrafica aggiuntiva non trovata - la inserisco
  {
    aa = new()
    aa.init()
    this.ImpostaCampiAnagraficaAggiuntiva(aa)
     
    if (!(aa.saveToDB(...)))
    {
       string errorMessage = Utility.recuperaErrori(aa)
       this.addDocumentError(errorMessage)
    }
  }
}
 
// Cancellazione
if (Phase == 3 && deleted)
{
  AnagraficaAggiuntiva aa = new()
  aa.CodiceAnagrafica = CodiceCliente
   
  try 
  {
    aa.loadFromDB(...)
    aa.deleted = true
     
    if (!(aa.saveToDB(...)))
    {
       string errorMessage = Utility.recuperaErrori(aa)
       this.addDocumentError(errorMessage)
    }
  }
  catch  // Anagrafica aggiuntiva non trovata
  {
    // Non è un errore tanto stavo cancellando e quindi non devo fare nulla
     
  }
}

In questo evento sono gestiti i casi di inserimento di un nuovo Cliente, modifica e cancellazione e per ognuno di essi è definito il codice specifico di trattamento.

Quando sto per inserire un nuovo Cliente creo una nuova istanza di AnagraficaAggiuntiva, imposto il valore dei suoi campi dalle proprietà aggiuntive di Cliente e poi salvo i dati.

Quando sto per modificare un Cliente vado a leggere i dati del documento AnagraficaAggiuntiva, imposto il valore dei suoi campi dalle proprietà aggiuntive di Cliente e poi salvo i dati.

In caso di cancellazione di un Cliente vado a leggere i dati del documento AnagraficaAggiuntiva e poi lo cancello.

Il metodo recuperaErrori analizza un documento e restituisce una stringa con gli errori ad esso associati..

Vi allego qui di seguito il progetto di Instant Developer Foundation che gestisce questa problematica.

Tabelle Correlate.zip (528,2 KB)

Fatemi sapere se può essere interessante

4 Mi Piace

Interessante. Si potrebbe provare con due classi ClientiFull e FornitoriFull, entrambe legate ad AnagraficheAggiuntive, una che estende la classe Clienti e una la classe Fornitori (legate ognuna alla propria tabella), e le due videate da ClientiFull e FornitoriFull. Chissà se il framework si arrangia a far tutto :thinking:

2 Mi Piace

:thinking:
@r.bianco ci avevo pensato ma non essendoci un legame diretto tra le due tabelle con un FK non credo che funzioni, ma una prova la voglio fare.

Vi tengo informati.

2 Mi Piace

Ho fatto una prova veloce e funziona!
Confeziono meglio l’esempio e lo spiego e metto nel prossimo post.

2 Mi Piace

Ho completato l’esempio con anche la soluzione proposta da @r.bianco.
Tabelle Correlate Due.zip (549,1 KB)

In questo progetto ho aggiunto un altro componente (Componente Due) con i documenti che servono e nell’applicazione anche le videate di questa seconda soluzione.
In Componente Due abbiamo i documenti:

  • Cliente Due
  • Fornitore Due
  • Anagrafica Aggiuntiva Due

Che derivano dalle relative tabelle.
Poi i due documenti:

  • Cliente Anagrafica aggiuntiva
  • Fornitore Anagrafica Aggiuntiva

Che derivano entrambi dalla tabella AnagraficheAggiuntive ma che estendono non IDDocument ma le classi Cliente Uno e Cliente Due.
Inoltre ad ognuna è stata aggiunta una master query per filtrare i record per il tipo anagrafica specifica (cliente o fornitore) e con in join la relativa tabella Clienti o Fornitori.

A questo punto gli unici eventi obbligatori da implementare sono OnInit per impostare il tipo anagrafica e OnEndTransaction per impostare il codice cliente o fornitore nel campo codice anagrafica.

In questo modo il tutto funziona grazie al frame work di Instant Developer Foundation.
Nelle videate Cliente e fornitore ho nascosto i campi:

  • Tipo Anagrafica
  • Progressivo
  • Codice Anagrafica

Questa soluzione ha come limite che ogni record Cliente o Fornitore abbia il suo corrispondente record nella tabella AnagraficheAggiuntive.

2 Mi Piace

Non ci avevo pensato. Grazie!

1 Mi Piace