Modellare le relazioni in Dataverse
In Dataverse ogni relazione tra tabelle è un metadata object con un proprio insieme di comportamenti. Come developer PL-400 devi saper scegliere il tipo corretto e configurare il cascading behavior, perché queste scelte incidono su performance, sicurezza e integrità referenziale ben oltre la semplice struttura dati.
One-to-many (1:N) e lookup
La relazione one-to-many è il mattone fondamentale: crea automaticamente una colonna Lookup sulla tabella “many” (child) che punta alla tabella “one” (parent). Ogni lookup è tecnicamente un EntityReference composto da GUID + logical name della tabella target + testo primario. Quando crei una 1:N definisci anche come le operazioni sul parent si propagano al child.
Many-to-many (N:N)
Per le relazioni many-to-many hai due strade:
- Native N:N: Dataverse genera automaticamente una intersect table (relationship table) nascosta che memorizza solo le coppie di GUID. Semplice e veloce, ma non può avere colonne aggiuntive né logica: è pura associazione (associate/disassociate).
- Manual N:N con junction table: crei una tabella intermedia esplicita collegata da due relazioni 1:N. La scegli quando devi memorizzare attributi sulla relazione stessa (data, quantità, stato, prezzo) o applicare business rules, plug-in e security a livello di riga di collegamento.
Regola d’esame: se lo scenario richiede metadati sull’associazione, serve la junction table; se basta collegare/scollegare record, la native N:N è sufficiente.
Lookup polymorphic e Customer
Una lookup polymorphic può puntare a più tabelle target. L’esempio classico è la colonna Customer, che può riferirsi sia ad Account sia a Contact. Anche Owner (User o Team) e il Regarding delle activity sono polymorphic. Sotto il cofano sono più relazioni 1:N verso ciascun target: nel codice devi sempre leggere il LogicalName dell’EntityReference, perché il GUID da solo non ti dice quale tabella stai gestendo.
Cascading behaviors
Il cascading behavior definisce come le azioni sul parent si propagano ai child, per ciascuna operazione: Assign, Share, Unshare, Reparent, Delete e Merge. Le configurazioni principali:
- Referential (no cascade): parent e child restano indipendenti. Assign e Share non si propagano; eliminando il parent il lookup viene azzerato (Remove Link) oppure bloccato con Referential, Restrict Delete. È la scelta più leggera e la più comune per relazioni “loose”.
- Parental: massima propagazione. Tutto ciò che accade al parent (assign, share, delete, reparent) cascata sui child. Comodo per gerarchie forti, ma pericoloso perché eredita anche ownership e security.
- Configurable Cascade (custom): imposti l’azione per ciascuna operazione — Cascade All, Cascade Active, Cascade User-Owned, Cascade None, Remove Link, Restrict. Massimo controllo granulare (es. cascata solo sui record attivi).
Impatto su ownership, sharing e delete
- Delete: con Parental o Cascade All, eliminando il parent elimini a catena tutti i child. Con Referential + Restrict il delete del parent è bloccato finché esistono child.
- Share: Parental propaga i privilegi di condivisione popolando la tabella POA (Principal Object Access), che può gonfiarsi rapidamente.
- Assign/Reparent: Parental riassegna anche tutti i child al nuovo owner, con possibili operazioni massive.
Trappole tipiche d’esame
- Scenario: eliminando un Account “spariscono” centinaia di record collegati non voluti → la relazione è Parental (o Cascade All) sul Delete; imposta Referential con Remove Link o Restrict per proteggere i child.
- Scenario: condividere un parent degrada le performance e fa crescere la tabella POA → è la cascata Share di una relazione Parental; passa a Referential o a Configurable Cascade con Share = Cascade None.
- Scenario: devi memorizzare quantità e prezzo sull’associazione prodotto↔ordine → non usare la native N:N; crea una junction table con due relazioni 1:N.
- Scenario: una colonna deve puntare sia ad Account che a Contact → usa la lookup Customer (polymorphic), non due lookup separate; nel plug-in leggi il
LogicalName. - Scenario: riassegnando l’owner del parent cambiano owner anche decine di child, con timeout → è la cascata Assign di una relazione Parental; valuta Configurable Cascade con Assign = Cascade None o Cascade User-Owned.