2008-11-04 7 views
1

J'ai essayé de concevoir un schéma de base de données pour un projet parallèle, mais je n'ai pas été en mesure de produire tout ce que je suis à l'aise avec. J'utilise ASP.Net avec LINQ pour mon accès aux données:Conception de base de données concernant les entrées dynamiques - Une ligne ou plusieurs lignes?

Je vais autoriser les utilisateurs à spécifier jusqu'à 10 "éléments" chacun avec 2 propriétés numériques, et 1 propriété référentielle, le nom de l'élément.

Si je devais mettre cette entrée en 1 ligne, il serait facilement égal à plus de 30 colonnes (minimum), par ex. item_1_name (ref) item_1_weight item_1_volume item_2_name ... etc ...

Et je ne peux pas simplement transformer ces colonnes dans les tables référentiels que chaque propriété peut varier essentiellement de 1 à 400+. J'ai également pensé que si un utilisateur décide de mettre un seul élément dans son entrée, la méthode dont je crée l'objet pour ces données sera statique, car avec LINQ, je devrais vérifier si les propriétés et whatnot sont NULL et travaille en conséquence. De plus, si jamais je voulais augmenter le nombre d'éléments autorisés dans une entrée, ce serait un casse-tête de travailler avec.

L'autre option à laquelle j'ai pensé consiste simplement à créer une ligne pour chaque élément et à l'attacher avec un identifiant d'entrée. Donc, je n'aurais pratiquement jamais d'entrées nulles, mais ma table deviendrait astronomique mais pas très large, car il n'y aurait que 5 colonnes impaires.

Y at-il quelque chose que je néglige dans ma conception/y a-t-il une façon beaucoup plus efficace de le faire?

EDIT: Quand je dis qu'il va croître astronomiquement, je veux dire dans ce sens: Un utilisateur peut créer une entrée, et chaque entrée aura très probablement un groupe d'éléments. Donc, disons qu'ils font une entrée par jour sur le site, ils pourraient avoir 3 groupes d'articles, avec le nombre maximum d'articles (10), ce qui équivaudrait à 30 articles pour cette seule entrée. Faire une entrée tous les jours pendant une semaine à ce rythme et vous pourriez avoir 210 lignes pour cet utilisateur unique.

Répondre

2

Je vous recommande ce dernier modèle que vous mentionnez, créez une table en fonction de cinq colonnes:

CREATE TABLE Items (
    user_id    INTEGER NOT NULL, 
    item_id    INTEGER NOT NULL DEFAULT 1, 
    numeric_property1  INTEGER, 
    numeric_property2  INTEGER, 
    referential_property INTEGER, 
    PRIMARY KEY (user_id, item_id), 
    FOREIGN KEY (user_id) REFERENCES Users(user_id) 
         ON DELETE CASCADE, 
    FOREIGN KEY (item_id) REFERENCES num_items(item_id), 
    FOREIGN KEY (referential_property) REFERENCES some_other_table(some_column) 
); 

Je montre une table num_items ci-dessus, qui contient les numéros 1 à 10 si vous souhaitez limiter les utilisateurs à 10 articles au maximum:

CREATE TABLE num_items (item_id INTEGER NOT NULL); 
INSERT INTO num_items (item_id) 
    VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); 

les avantages de ce modèle est qu'il est facile de COUNT() combien d'éléments d'un utilisateur donné, il est facile de calculer des choses comme MIN() et MAX() pour une propriété donnée, vous pouvez appliquer une clé étrangère pour la propriété référentielle, etc.

Certaines bases de données ont une caractéristique de déclarer la deuxième partie d'une clé primaire composé (item_id dans ce cas) comme auto-incrémentées, donc si vous spécifiez la valeur pour entity_id mais omettez item_id il obtient automatiquement la valeur suivante non utilisée (mais ne remplit pas les vides si vous en supprimez un). Vous n'indiquez pas quelle marque de base de données vous utilisez, donc je vous laisse le soin de comprendre cette fonctionnalité.

edit: Comme le dit Tony Andrews dans sa réponse, le nombre de lignes n'est pas un problème. Vous n'indiquez pas quelle marque de base de données vous souhaitez utiliser, mais à moins de choisir un produit particulièrement faible comme MS Access, vous pouvez compter sur la base de données pour traiter facilement des millions de lignes. Si vous choisissez bien les index et écrivez des requêtes qui utilisent ces index, l'efficacité ne devrait pas poser de problème.

+0

Ne serait-il pas préférable d'utiliser une contrainte CHECK pour item_id au lieu d'une clé étrangère? – Dave

+0

Vérifier mes modifications. Je suis d'accord, mais je suis toujours préoccupé par l'efficacité de ce que je vais faire car le nombre de lignes va être énorme. – MunkiPhD

+0

Oui, vous pouvez utiliser une contrainte CHECK mais lorsque vous devez étendre à 12 éléments, la modification d'une contrainte CHECK est un changement de métadonnées (ALTER TABLE), et cela peut être coûteux. L'insertion de valeurs (11), (12) est un changement de données facile. –

0

utiliser une seule table d'objet:

userId, itemIndex, IsReference, numericValue, referenceValue

cette façon la valeur de item_3_name pour l'utilisateur 999 se traduit par

999,3, true, null, valeur

Vous devrez appliquer certaines contraintes vous même le nombre maximal d'éléments par utilisateur, etc.

+0

Vous décrivez la conception EAV, qui présente de nombreux problèmes d'évolutivité et d'intégrité référentielle. Par exemple, comment déclarez-vous une clé étrangère sur la propriété référentielle? –

0

Une conception de base de données appropriée consisterait à stocker chaque utilisateur/article dans une rangée distincte. Ce sera beaucoup plus facile de travailler avec, et supprime la restriction arbitraire de 10 éléments. Je ne dirais pas qu'il va se développer "astronomiquement", il y aura environ 10 x (nombre d'utilisateurs) lignes.

Questions connexes