2010-11-05 4 views
1

Il est possible que cette question soit une réponse simple qui est une pratique standard, ou n'a pas de réponse parce que cela ne peut pas être fait pour une raison simple, ou est simplement un exercice de pensée intéressant. Je suis actuellement assis sur la dernière option, mais en espérant la première ...Tables de surtryptage - L'héritage multiple est-il possible?

Disons que je veux créer un «groupe» ou une «classe» d'entités dans mon modèle de données. En général, j'utiliser une table supertype comme ceci:

DrivableEntity 
---------- 
ID (PK, auto-increment) 
Type (int or otherwise some kind of enum) 

Car 
---------- 
ID (PK, FK to DrivableEntity) 
(car-specific fields) 

Bike 
---------- 
ID (PK, FK to DrivableEntity) 
(bike-specific fields) 

Alors mes inserts probablement passer par ce qui ressemble à l'extérieur comme une procédure de CRUD pour chaque sous-table, mais insère à l'intérieur dans DrivableEntity et utilise ensuite l'identité de portée insérer dans la table prévue. Etant plus un programmeur qu'un modélisateur de données, cela m'a fait penser à l'héritage des objets. Pour l'héritage direct, c'est génial. Les données/tâches communes peuvent être extraites d'un niveau, la substitution de Liskov peut être maintenue, etc. Mais l'héritage multiple est-il possible dans un modèle de données? Je suis principalement un développeur C#, j'ai donc commencé à penser en termes d'interfaces. Que se passe-t-il si je veux exposer des tableaux qui ont "implémenté" IDrivable et/ou ITowable, etc. Est-ce que quelque chose comme ça est possible? Est-ce que quelqu'un a déjà fait quelque chose comme ça?

Répondre

1

En général, deux approches du travail de modèle de données bien pour ce que vous avez décrit.

Le modèle que vous avez déjà décrit est l'une des approches, et a l'avantage d'être très "bien rangé". Cela fonctionne particulièrement bien si vous avez un grand nombre de colonnes dans les tables, donc la taille d'un objet individuel n'est pas trop grande ou trop large.

DrivableEntity 
---------- 
ID (PK, auto-increment) 
Type (int or otherwise some kind of enum) 

Car 
---------- 
ID (PK, FK to DrivableEntity) 
(car-specific fields) 

Bike 
---------- 
ID (PK, FK to DrivableEntity) 
(bike-specific fields) 

L'autre approche est de garder toutes les colonnes d'une table être nulles seule et marquer chaque ligne avec un indicateur de type. Cette approche peut devenir rapidement désordonnée, mais a beaucoup moins de frais généraux pour les cas simples.

Vous pouvez modéliser l'héritage ou les interfaces dans votre modèle d'origine, simplement en ajoutant une autre colonne de clé étrangère à l'une des entités "dérivées". Par exemple:

FlyableEntity 
------------- 
ID (PK) 
... flyable attributes 

FlyingCar (implements/inherits IDrivable and IFlyable) 
------------- 
DrivableEntityID (PK, FK) 
FlyableEntityID (PK, FK) 
... add flying car attributes 

or: 

FlyingCar (inherits from Car) 
------------- 
CarID (PK, FK) 
FlyableEntityID (FK) 
... add flying car attributes 
+0

Certainement pas une approche aussi élégante que je l'espérais, mais logiquement, elle correspond certainement. Je pense que ce que je cherche vraiment à faire ne sera pas réalisable dans un modèle relationnel comme SQL Server. Cependant, cette approche peut être utile pour le projet. Merci! – David

1

David,

Entity Framework a la capacité d'utiliser l'héritage. This is good overview of inheritance in the Entity Framework. Vous pouvez utiliser POCO avec EF pour créer vos propres interfaces pour fournir l'accès aux données.

La situation que vous décrivez n'est pas vraiment de l'héritage multiple, car vous avez une table/entité de base et des tables/entités dérivées. Pour modéliser ceci dans EF, vous créez une entité de base, puis créez chaque entité enfant. À ce stade, vous pouvez mapper les propriétés d'entité enfant de chaque type à la table correcte. Cela dit, votre logique d'insertion/mise à jour/suppression va devenir très complexe. Entity Framework peut rencontrer des problèmes avec un modèle complexe.

La question que je voudrais savoir, pourquoi faites-vous cela? Si c'est pour partager des données communes entre les types, je recommanderais de créer des vues sur le serveur qui rejoignent la table parent avec les tables enfants. Ce sera beaucoup plus rapide, et vous pouvez gérer les opérations CUD (créer/mettre à jour/supprimer) avec un instead of trigger ce qui rendra SQL plus facile, car il y a une séparation claire entre l'accès aux données et le stockage des données.

Est-ce que cela a du sens?

Erick

0

Vous pouvez créer des vues pour résoudre ce problème.

viewDriveableCar
ViewDrivabaleBike
ViewTowableCar

ensuite combiner les vues en une vue superbe combinaison des entités carrossables et tractables à l'aide d'un syndicat. Vous ne pouvez inclure que les colonnes communes aux deux. Noms similaires mais différentes devront être normalisées:

CREATE VIEW vrDiveTow 
AS 

SELECT 
viewDriveableCar.CarId as ID, 
... other attributes 

UNION 

SELECT 
viewTowableCar.TowableId as ID, 
... other attributes 
UNION 

Un grand Gotcha. SQL utilise des plans de requête qui peuvent être mis en cache pour produire les résultats. Si le plan de requête de SQL est construit autour de l'interrogation de 'Seven-Up' et que vous filtrez pour 'Coke', alors le plan de requête est inefficace et une analyse de table complète est utilisée.

0

Le sous-typage est possible mais également déconseillé. Les bases de données sont uniques et vous ne devriez pas essayer d'introduire les principes de la POO dans ce monde. Beaucoup ont essayé, beaucoup ont échoué. Si vous essayez de penser à des "objets" de base de données en termes de POO, votre base de données en souffrira.

+0

C'est le sentiment que j'ai aussi. L'objectif principal était que la première exigence pour la DAL sur ce projet est "il ne doit pas être un ORM". Donc essayer de conduire les principes OO appropriés dans le code est déjà une bataille difficile. – David

+0

L'exigence est parfaitement saine. Sans vouloir offenser, mais à partir de vos questions/commentaires, j'ai l'impression que vous n'êtes pas très familier avec les bases de données et que vous avez été un peu forcé de développer ces solutions. Vous devriez vraiment obtenir un développeur DB pour concevoir la base de données pour vous. –