Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Mettre à jour la valeur de la clé primaire à l'aide du cadre d'entité

J'ai un doctorat. en cs - dans le domaine des bases de données, cette réponse sera donc un peu différente de la perspective d'un programmeur. Avec tout le respect que je dois à Oliver Hanappi, une clé peut changer et change parfois si ce n'est pas une clé de substitution. Par exemple. Une clé naturelle ou une clé composée. Par example. Il est possible de faire changer votre SSN aux États-Unis. Mais de nombreux programmeurs au fil des ans considéreraient cela comme une clé immuable et l'utiliseraient comme telle. Il est beaucoup plus courant de changer une clé primaire composée de clés étrangères.

J'ai affaire à une base de données qui a une relation ternaire. Plus précisément trois entités (les clés étrangères étant des clés primaires de substitution dans leurs tables respectives). Cependant, pour préserver la relation entre deux entités tout en modifiant la troisième entité nécessite modification d'une partie de la clé primaire de la table d'intersection (également appelée table de jointure pure sur MSDN). Il s'agit d'une conception valide et ne pourrait être améliorée qu'en supprimant la table d'intersection de relations ternaires et en la remplaçant par deux tables de relations binaires (qui peuvent avoir leurs propres clés de substitution). EF gèrerait cette amende. Cette modification de conception créerait un modèle (Plusieurs->plusieurs)->plusieurs ou Parent1-Parent2 -> Enfant-petit-enfant (si ce n'est pas clair, lisez l'exemple ci-dessous). Le cadre d'entité fonctionnerait bien avec cela car chaque relation est vraiment une relation un à plusieurs. Mais c'est une conception folle du point de vue de la DB. Laissez-moi vous montrer un exemple pourquoi.

Considérez que le cours, la salle de classe et l'instructeur sont associés les uns aux autres dans une classe. La classe peut inclure :CourseID, ClassroomID, InstructorID en tant que clés étrangères et contenir une clé primaire composée comprenant les trois. Bien qu'il s'agisse d'un modèle ternaire clair et concis (relation à 3 voies), nous pourrions le diviser en relations binaires. Cela donnerait deux tables d'intersection. L'ajout de clés de substitution satisferait EF comme suit :

Classe(SurrogateKeyClass , ID de l'instructeur , ID de cours )

ClassRoomUsed(SurrogateKeyClassroomUsed , SurrogateKeyClass , ID de salle de classe )

Le problème avec cette conception est que nous pourrions avoir le même cours et le même instructeur associés plusieurs fois, ce que le modèle précédent évite. Pour éviter ce problème, vous pouvez ajouter une contrainte dans la base de données pour l'unicité des deux champs ID, mais pourquoi voudriez-vous faire cela alors que vous ne traitez que des clés de substitution pour commencer ? Cependant, cette solution fonctionnerait du mieux que je sache. Ce n'est cependant pas une conception de base de données logique en raison de la contrainte unique non naturelle requise dans la base de données.

MAIS, si vous ne voulez pas changer votre base de données ou ne pouvez pas changer votre base de données, voici une seconde solution :Les tables d'intersection/d'association ne sont que cela, des liens reliant deux entités ou plus ensemble. En cas de changement, supprimez l'association et recréez-en une nouvelle qui possède les clés étrangères appropriées (propriétés de navigation). Cela signifie que vous ne serez pas autorisé à exiger des entités enfants dans aucune des relations, mais c'est extrêmement courant.

Je suggérerais que l'Entity Framework (à l'avenir) permette à ceux d'entre nous qui peuvent concevoir un modèle de base de données élégant de modifier des parties de clés dans les tables d'intersection/d'association quand nous le voulons !

Un autre exemple gratuit :

Envisagez une association d'étudiants, de cours et de notes. Les étudiants sont associés à un cours via une note. Il s'agit généralement d'une association plusieurs à plusieurs entre l'étudiant et un cours avec un champ supplémentaire dans la table d'association appelée note (les tables d'association ont des données de charge utile comme la note, les tables d'intersection n'ont pas de charge utile et sont référencées dans MSDN en tant que tables de jointure pures à bail en un seul endroit):

Étudiant(ID étudiant , ......)

Cours(IDCours , ...)

Prendre(StudentID , ID de cours , note)

Si quelqu'un fait une erreur de saisie de données à partir d'un menu déroulant et place un étudiant dans la mauvaise classe, vous souhaitez qu'il le modifie plus tard en sélectionnant à nouveau le menu déroulant et en sélectionnant un autre cours. En arrière-plan, vous devrez supprimer l'objet EF de la table de prise et le recréer sans perdre de note s'il y en a une. Changer simplement la clé étrangère CourseID semble être une meilleure alternative. Créez votre propre association si celle-ci semble artificielle, mais en tant que professeur, c'était naturel pour moi.

Conclusion :lorsque vous avez une chaîne de relations, il peut être préférable de ne pas autoriser la mise en cascade et/ou la modification de FK, mais il existe des scénarios raisonnables/logiques où cela est nécessaire, même s'il n'est pas recommandé en tant que meilleure pratique dans général .

Ce problème peut se manifester avec les exceptions suivantes selon que vous modifiez respectivement la propriété de navigation ou la propriété de clé dans le modèle :

Une violation de contrainte d'intégrité référentielle s'est produite :une propriété de clé primaire qui fait partie de la contrainte d'intégrité référentielle ne peut pas être modifiée lorsque l'objet dépendant est Inchangé, sauf s'il est défini sur l'objet principal de l'association. L'objet principal doit être suivi et non marqué pour suppression.

La propriété 'X' fait partie des informations clés de l'objet et ne peut pas être modifiée.