Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Aggiorna il valore della chiave primaria utilizzando il framework di entità

Ho un dottorato di ricerca in cs - nell'area dei database, quindi questa risposta sarà leggermente diversa dalla prospettiva di un programmatore. Con tutto il rispetto per Oliver Hanappi, una chiave può cambiare e occasionalmente cambia se non è una chiave surrogata. Per esempio. Una chiave naturale o una chiave composit. Per esempio. È possibile cambiare il tuo SSN negli Stati Uniti. Ma molti programmatori nel corso degli anni la considererebbero una chiave immutabile e la userebbero come tale. È molto più comune modificare una chiave primaria composita composta da chiavi esterne.

Ho a che fare con un database che ha una relazione ternaria. In particolare tre entità (con chiavi esterne che sono chiavi primarie surrogate nelle rispettive tabelle). Tuttavia, per preservare la relazione tra due entità mentre si modifica la terza entità richiede modifica di parte della chiave primaria della tabella di intersezione (denominata anche tabella di join puro su MSDN). Questo è un progetto valido e può essere migliorato solo rimuovendo la tabella di intersezione delle relazioni ternarie e sostituendola con due tabelle di relazioni binarie (che potrebbero avere le proprie chiavi surrogate). EF gestirebbe questa multa. Questa modifica al design creerebbe un modello (Molti->Molti)->Molti o Genitore1-Genitore2 -> Figlio-nipote (se non è chiaro, leggi l'esempio di seguito). La struttura dell'entità funzionerebbe bene con questo poiché ogni relazione è davvero una relazione uno a molti. Ma è un design pazzesco dal punto di vista DB. Lascia che ti mostri un esempio del perché.

Considera che Corso, Aula e Istruttore sono associati tra loro in una classe. La classe potrebbe includere:CourseID, ClassroomID, InstructorID come chiavi esterne e contenere una chiave primaria composit che include tutte e tre. Sebbene sia un modello ternario chiaro e conciso (relazione a 3 vie) potremmo scomporlo in relazioni binarie. Questo darebbe due tabelle di intersezione. L'aggiunta di chiavi surrogate soddisferebbe EF come segue:

Classe(SurrogateKeyClass , ID istruttore , ID corso )

ClassRoomUsed(SurrogateKeyClassroomUsed , SurrogateKeyClass , ClassRoomID )

Il problema con questo progetto è che potremmo avere lo stesso corso e istruttore associati più volte, cosa che il modello precedente evita. Per evitare questo problema, puoi aggiungere un vincolo nel database per l'unicità dei due campi ID, ma perché vorresti farlo quando hai a che fare solo con chiavi surrogate per cominciare? Tuttavia questa soluzione funzionerebbe nel miglior modo possibile. Questo non è tuttavia un progetto di database logico a causa del vincolo univoco innaturale richiesto nel DB.

MA, se non vuoi cambiare il tuo database o non puoi cambiare il tuo database, ecco una seconda soluzione :le tabelle di intersezione/associazione sono proprio questo, collegamenti che collegano due o più entità insieme. In caso di modifica, eliminare l'associazione e ricrearne una nuova con le chiavi esterne appropriate (proprietà di navigazione). Ciò significa che non ti sarà consentito richiedere entità figlio in nessuna delle relazioni, ma è estremamente comune.

Suggerirei che Entity Framework (in futuro) consenta a quelli di noi che possono progettare un modello DB elegante di modificare parti di chiavi nelle tabelle di intersezione/associazione quando vogliamo!

Un altro esempio gratuito:

Considera uno studente, un corso, un'associazione di voti. Gli studenti sono associati a un corso tramite un voto. Di solito si tratta di un'associazione da molti a molti tra Studente e un corso con un campo aggiuntivo nella tabella di associazione chiamato voto (le tabelle di associazione hanno dati di carico utile come voto, le tabelle di intersezione non hanno un carico utile e sono indicate in MSDN come tabelle di unione pura in locazione in un unico luogo):

Studente(ID studente , ....)

Corso(ID corso , ...)

Prendendo(ID studente , ID corso , voto)

Se qualcuno commette un errore di immissione dei dati da un menu a discesa e inserisce uno studente nella classe sbagliata, desideri che lo cambino in seguito selezionando nuovamente il menu a discesa e selezionando un corso diverso. In background dovrai eliminare l'oggetto EF dalla tabella Taking e ricrearlo senza perdere un voto se ce n'è uno. Semplicemente cambiando la chiave esterna CourseID mi sembra un'alternativa migliore Vieni con la tua associazione se questa sembra artificiosa, ma come professore è stato naturale per me.

Conclusione:quando si dispone di una serie di relazioni, potrebbe essere meglio non consentire il collegamento a cascata e/o la modifica di FK, ma esistono scenari logici/ragionevoli in cui è necessario, anche se non consigliati come best practice in generale .

Questo problema può manifestarsi con le seguenti eccezioni a seconda che tu stia modificando rispettivamente la proprietà di navigazione o la proprietà della chiave nel modello:

Si è verificata una violazione del vincolo di integrità referenziale:una proprietà della chiave primaria che fa parte del vincolo di integrità referenziale non può essere modificata quando l'oggetto dipendente è Invariato a meno che non sia impostato sull'oggetto principale dell'associazione. L'oggetto principale deve essere tracciato e non contrassegnato per l'eliminazione.

La proprietà 'X' fa parte delle informazioni chiave dell'oggetto e non può essere modificata.