Faire démarrer quelques projets avec EF, mais j'avais quelques questions sur les tables de jointure et les clés, etc. Disons que j'ai une table d'applications et une table d'autorisations. Les applications ont de nombreuses autorisations et chaque autorisation peut appartenir à de nombreuses applications (plusieurs à plusieurs).
Maintenant, les tables d'application et d'autorisation sont faciles:
Applications
--------------
PK ApplicationID
Name
Permissions
--------------
PK PermissionID
Name
Mais quelle est la MEILLEURE façon de faire la table de jointure? J'ai ces deux options:
ApplicationPermissions
-----------------------
PK ApplicationPermissionID
CU ApplicationID
CU PermissionID
OU
ApplicationPermissions
-----------------------
CPK ApplicationID
CPK PermissionID
PK = Primary Key
CPK = Composite Primary Key
CU = Composite Unique Index
Avez-vous déjà été brûlé en le faisant d'une manière par rapport à l'autre? est-ce strictement une préférence? Il m'est venu à l'esprit que beaucoup de "différences" seront résumées par mon modèle de référentiel (par exemple, je ne créerais presque jamais un objet d'autorisation entier et l'ajouterais à une application, mais le faire par ID ou nom unique ou quelque chose), mais je suppose que je cherche des histoires d'horreur, d'une manière ou d'une autre.
la source
Au fil des ans, j'ai pris l'habitude de donner à chaque table "TableName" une clé primaire générée automatiquement "TableNameID", sans aucune exception, pas même pour les tables de jonction. Je peux dire que je ne l'ai jamais regretté, car cela facilite beaucoup de choses lors de la création de code générique qui fait quelque chose pour "toutes les tables" ou "certaines tables", ou pour "beaucoup de lignes de plusieurs tables différentes".
Par exemple, si quelqu'un vous demande de stocker des lignes de tables différentes (ou des références à celles-ci) dans un fichier ou en mémoire, par exemple, à des fins de journalisation, il est très pratique lorsque vous savez au préalable que vous avez juste besoin d'en stocker exactement une nom de la table et exactement un ID entier, et vous n'avez pas à vous occuper de "cas spéciaux".
Une autre chose, lorsque vous commencez avec des PK combinés, vous rencontrerez probablement quelques fois plus tard le besoin de clés étrangères combinées (car vous pouvez arriver à un point où vous souhaitez ajouter une référence FK à votre
ApplicationPermissions
table). Ensuite, la prochaine exigence peut être que ce FK soit unique en conjonction avec d'autres attributs ou clés étrangères - ce qui entraînera une complexité globale accrue. Rien de ce qui n'est pas possible à gérer pour la plupart des systèmes DB modernes, bien sûr, mais une solution uniforme facilite souvent la vie des programmeurs.Et enfin, une déclaration comme
SELECT ... FROM TABLE WHERE TableNameID IN (id1,id2,...)
ça fonctionne bien avec une seule colonne comme clé primaire, mais je n'ai jamais vu de dialecte SQL jusqu'à présent qui vous permet de le faire avec des clés combinées. Si vous savez à l'avance que vous n'aurez jamais besoin d'une requête comme celle-ci, très bien, mais ne soyez pas surpris si demain vous obtenez une exigence qui sera résolue le plus facilement avec ce type de SQL.Bien sûr, lorsque vous vous attendez à ce que votre
ApplicationPermissions
table contienne plusieurs centaines de millions de lignes, vous devriez alors éviter quelque chose comme aApplicationPermissionsID
.la source
Bien que la réponse de Mike soit bonne, voici les raisons pour lesquelles j'ajouterais un champ ID distinct ou non.
Envisagez d'utiliser un champ d'ID distinct pour la table de jonction / jointure si elle contient des champs autres que l'ID . Cela tend à noter qu'il s'agit d'une entité de première classe.
Envisagez d'utiliser un champ ID distinct si les API ou toute logique existante ont tendance à utiliser des champs uniques pour récupérer / modifier des entités. Cela peut aider d'autres personnes à suivre votre code dans le cadre d'un projet plus vaste.
Ne l'utilisez pas s'il n'y a aucun avantage spécifique (KISS). EF sait comment gérer ce type de table et une contrainte composite unique peut parfois être manquée lorsque d'autres personnes tentent de comprendre ce type de relation. De plus, lors de la normalisation, j'essaie d'utiliser la plus petite clé possible qui définit de manière unique le tuple . Dans votre deuxième exemple, vous avez effectivement 2 clés primaires candidates distinctes.
la source
N'oubliez pas de créer un index et une clé étrangère sur
PersonId
etAddressId
.Peu importe ce que les autres pensent être "meilleur" ou "vous devriez", c'est le moyen le plus simple et le plus facile de permettre à la base de données de fonctionner correctement.
la source
PersonAddress
lignes à l' identiquePersonId
et lesAddressId
valeurs.