Quels sont les modèles de conception à l'appui de champs personnalisés dans une application?
Nous développons une application commerciale. Nos clients demandent des champs personnalisés de soutien. Par exemple, ils veulent ajouter un champ dans le formulaire Client.
Ce que sont connus les modèles de conception pour stocker les valeurs de champ et les méta-données sur les champs?
Je vois ces options pour l'instant:
Option 1: Ajouter Champ1, Champ2, Champ3, Field4 les colonnes de type varchar à ma table Client.
Option 2: Ajouter une seule colonne de type XML dans la table client et stocker les champs personnalisés' valeurs dans xml.
Option 3: Ajouter un CustomerCustomFieldValue table avec une colonne de type varchar et de stocker des valeurs dans cette colonne. Cette table aurait également un code client, un CustomFieldID.
CustomerID, CustomFieldID, Value
10001, 1001, '02/12/2009 8:00 AM'
10001, 1002, '18.26'
10002, 1001, '01/12/2009 8:00 AM'
10002, 1002, '50.26'
CustomFieldID serait un ID d'une autre table appelée Personnalisé avec ces colonnes: CustomFieldID, FieldName, FieldValueTypeID.
Option 4: Ajouter un CustomerCustomFieldValue tableau avec une colonne pour chaque type de valeur et de stocker des valeurs dans la colonne de droite. Semblable au n ° 3, mais les valeurs de champ sont stockées à l'aide d'une forte colonne type.
CustomerID, CustomFieldID, DateValue, StringValue, NumericValue
10001, 1001, 02/12/2009 8:00 AM, null, null
10001, 1002, null, null, 18.26
10002, 1001, 01/12/2009 8:00 AM, null, null
10002, 1002, null, null, 50.26
Option 5: Options 3 et 4, utiliser un tableau spécifique à un seul concept (le Client). Nos clients demandent champ personnalisé dans d'autres formes. Devrions-nous plutôt nous disposons d'un système à l'échelle de champ personnalisé système de stockage? Donc au lieu d'avoir plusieurs tables comme CustomerCustomFieldValue, EmployeeCustomFieldValue, InvoiceCustomFieldValue, nous aurions une seule table nommée CustomFieldValue? Bien qu'il semble plus élégant de moi, ne serait-ce pas provoquer un goulot d'étranglement des performances?
Avez-vous utilisé l'un de ces approches? Avez-vous réussi? Quelle est l'approche qui choisiriez-vous?
Connaissez-vous une autre approche que je dois prendre en compte?
Aussi, mes clients veulent le champ personnalisé pour être en mesure de se référer à des données d'autres tables. Par exemple, un client peut vouloir ajouter un "moyen de Paiement Préféré" pour le Client. Les méthodes de paiement sont définis ailleurs dans le système. Qu'apporte le thème de la "clés étrangères" dans l'image. Devrais-je essayer de créer des contraintes pour assurer que les valeurs stockées dans le champ personnalisé tableaux sont des valeurs valides?
Grâce
======================
MODIFIER 07-27-2009:
Merci pour vos réponses. Il semble que la liste des approches est très complète. J'ai choisi l'option 2 (une seule colonne XML). Il était le plus facile à mettre en œuvre pour l'instant. Je vais probablement avoir à lunette à un plus fortement défini par l'approche de mes exigences deviennent plus complexes et que le nombre de champs personnalisés de soutien va s'agrandir.
- Une extension de l'option 2 est la sérialisation binaire au lieu de XML. Comme vous l'avez demandé à ce que les modèles de conception sont là - Martin Fowler appelle cette Sérialisé LOB dans son livre Patterns d'Architecture d'Applications d'Entreprise - voir martinfowler.com/eaaCatalog/serializedLOB.html
- Je suis curieux de connaître le résultat de votre démarche choisie: avez-vous été en mesure d'effectuer le tri/recherche/filtrage sur les champs personnalisés à l'aide de XML (ou sérialisé LOB)? Était-ce suffisant pour vos besoins de stockage de données ou avez-vous dû prendre un autre itinéraire? Il serait génial si vous pouviez partager les connaissances.
- Vous n'avez pas de décrire comment le consommateur va utiliser ces données, et qui est un facteur important pour le choix de la solution de conception.
- Comment ce travail pour vous à la fin? Je me trouve face au même problème et de l'information sur le web semble éparses au mieux.
- L'option la plus simple (une colonne XML dans chaque tableau) s'est avéré bon. 7 ans plus tard, nous sommes sur le point de changer le design. Nous allons avec des temps d'exécution de la modification du schéma. Lorsqu'un client ajoute un champ, nous avons créer une nouvelle colonne dans la base de données à la volée, avec le bon type de données et le bon de clé étrangère pour les autres tables. Les principales raisons de ce changement: les types (intégrité des données), les clés étrangères (intégrité des données), la performance (index), la clarté (de l'interrogation et de scripts de migration est plus facile à écrire). XML a été facile à mettre en œuvre et nous a bien servi; c'est une option viable.
Vous devez vous connecter pour publier un commentaire.
Je suis d'accord avec les affiches ci-dessous que les Options 3, 4, ou 5 sont les plus susceptibles d'être appropriées. Cependant, chacun de vos implémentations a ses avantages et des coûts. Je vous suggère de choisir un par correspondant à vos besoins spécifiques. Par exemple:
Option 1 contre: les champs Personnalisés sont génériques, donc pas fortement typé champs. Table de base de données est inefficace, taille-sage avec de nombreux étrangers champs qui ne seront jamais utilisés. Nombre de champs personnalisés permis doit être prévu.
Option 2 inconvénients: Pas de DB actions possibles sur les champs personnalisés. C'est mieux si tout ce que vous devez faire, c'est afficher les champs personnalisés, plus tard, ou de faire des manipulations mineures des données uniquement sur une base Client.
Option 3 contre: Légère augmentation du temps de développement et la complexité de vos requêtes, mais il n'y a pas trop d'inconvénients, ici.
P. S. Comme indiqué ci-dessous, le terme "modèle de conception" se réfère généralement à la programmation orientée objet. Vous êtes à la recherche d'une solution à un problème de conception de base de données, ce qui signifie que la plupart des conseils sur les modèles de conception ne sera pas applicable.
Autant que le code de l'application, je n'en suis pas sûr. Je sais que les champs personnalisés de bénéficier grandement d'un Modèle EAV dans la base de données.
Par les commentaires ci-dessous, la plus grande erreur que vous pouvez faire avec ce modèle est de mettre les clés étrangères en elle. Jamais, jamais, jamais mettre quelque chose comme FriendID ou TypeID dans ce modèle. L'utilisation de ce modèle en collaboration avec la typique du modèle relationnel et de garder les champs de clé étrangère dans les colonnes de table comme ils le devraient.
Une deuxième erreur est de placer les données dans ce modèle qui doit être déclarée avec chaque élément. Par exemple de mettre quelque chose comme nom d'utilisateur dans ce modèle signifie que chaque fois que vous souhaitez accéder à un utilisateur et le besoin de connaître son nom d'utilisateur que vous avez commis-vous à une jointure, au mieux, ou 2n requêtes où n est le nombre d'utilisateurs vous êtes en train de regarder. Quand vous considérez que vous êtes généralement besoin de l'Identifiant de propriété pour chaque Utilisateur de l'élément, il devient évident que cela devrait rester dans les colonnes de la table.
Toutefois, si vous êtes simplement à l'aide de ce modèle avec les champs utilisateurs personnalisés, vous serez bien. Je ne peux pas imaginer de nombreuses situations où un utilisateur serait d'entrer dans les données relationnelles et l'EAV modèle n'est pas trop significativement préjudiciable aux recherches.
Enfin, n'essayez pas de joindre les données à partir de cela et d'obtenir un joli joli jeu d'enregistrements. Prenez l'original et puis, prenez l'ensemble des enregistrements de l'entité. Si vous trouvez vous-même tentés de rejoindre les tables que vous avez probablement fait la deuxième erreur comme mentionné ci-dessus.
Si vous êtes en développement avec un langage orienté objet, nous parlons adaptative modèles d'objet ici. Il ya tout à fait quelques articles écrits au sujet de la façon dont vous pouvez mettre en œuvre dans oo-langues, mais pas tellement d'informations sur la façon de concevoir la banque de données secondaires.
Dans la société où je travaille, nous avons résolu le problème en utilisant une base de données relationnelle pour stocker la COMPOSANTE de gestion des données. Nous avons entité centrale de la table pour la présentation de toutes les différentes "entités" dans le domaine, comme les gens, les périphériques réseau, les entreprises, etc... Nous entreposer des "champs de formulaire" à des tableaux de données sont typées, nous avons donc d'un tableau de chaînes, une pour les dates et ainsi de suite. Tous les tableaux de données ont une clé étrangère pointant vers la table d'entité. Nous avons aussi besoin de tables pour présenter le type du côté, c'est à dire ce genre d'attributs (champs de formulaire) peut certaine entité et cette information est utilisée pour interpréter les données dans les tables de données.
Avantages de notre solution sont que tout ce qui peut être modélisé sans modification du code, y compris les références entre les entités, multivalues et ainsi de suite. Il est également possible d'ajouter des règles de gestion et des validations sur les champs et ils peuvent être réutilisés dans toute forme. Les inconvénients sont que le modèle de programmation n'est pas très facile à comprendre et les performances de la requête sera pire qu'avec plus de DB typique de la conception. Une autre solution de base de données relationnelle aurait pu être mieux et plus facile pour la CG.
La construction d'une bonne CG avec une banque de données car c'est beaucoup de travail et je ne le recommande pas si vous n'avez pas hautement qualifiés développeurs. Peut-être qu'un jour il y aura un OS solution pour ces types d'exigences.
Champs personnalisés ont été discutées avant dans la:
Pour ajouter personnalisé/champs définis par l'utilisateur fonction ou pas?Quelque chose comme l'Option 3 est la façon de faire et j'ai utilisé cette méthode précédemment. Créer une table unique pour définir d'autres propriétés et leurs valeurs correspondantes. Ce serait une 1-N entre votre Client et CustomerCustomField tableau (respectivement). Votre deuxième question concernant la définition des relations avec les propriétés personnalisées serait quelque chose à penser. La première chose qui vient à l'esprit est l'ajout d'un champ de la source de données qui contient la table dans laquelle la valeur de propriété est lié. Donc, essentiellement, votre CustomerCustomField ressemblerait à:
Cela devrait vous permettre soit de se lier à une structure de données spécifique ou tout simplement pour vous permettre de spécifier indépendant des valeurs. Vous pouvez continuer à normaliser ce modèle, mais quelque chose comme cela pourrait fonctionner et devrait être assez facile à traiter dans le code.
Option 4 ou 5 serait mon choix. Si vos données est important, je n'irais pas jeter aux orties vos informations de type à l'Option 3. (Vous pourriez essayer de mettre en œuvre complète de la vérification de type vous-même, mais c'est un assez gros travail, et le moteur de base de données déjà fait pour vous.)
Quelques réflexions:
CustomFields
a unDataType
colonne.CustomFieldValues
pour s'assurer que la colonne spécifié parCustomFields.DataType
est non-nulle.DataType
.CustomerCustomFieldValue
, mais au lieu de cela, avec seulementCustomerID
etCustomFieldValueID
colonnes.Je me sers de ce dans une application en cours de développement. Il n'y a eu aucun problème pour le moment, mais EAV dessins encore effrayer les daylights hors de moi. Juste être prudent.
En aparté, XML peut également être un bon choix. Je ne sais pas que beaucoup à ce sujet à partir de l'expérience directe, mais elle a été l'une des options que j'ai pris en compte au début de la conception de données, et il avait l'air assez prometteur.
si ces "extra" les champs sont accessoires et ne se soucient pas de faire des recherches sur eux, j'ai l'habitude d'aller pour l'option 2 (mais comme JSON mieux que XML). Si il va y avoir des recherches sur des champs personnalisés, l'option 3 n'est pas difficile à faire, et généralement de l'optimiseur SQL pouvez obtenir des performances acceptables en sortir.
Je suis actuellement en train de travailler sur un projet avec ce même problème, et j'ai choisi d'utiliser l'option 3, mais j'ai ajouté un type de champs de champ et un ListSource champ dans le cas où le type de champs="liste". Le ListSource champ peut être une requête, une vue sql, le nom d'une fonction, ou quelque chose que les résultats dans une liste d'options de la liste. Le plus gros problème avec le fait d'essayer de stocker les champs comme ceci dans ma situation, c'est que ce champ liste peut changer, et les utilisateurs sont autorisés à modifier les données plus tard. Alors, que faire si la liste de champs a changé et ils vont à modifier. Ma solution à ce scénario était de permettre la modification uniquement si la liste n'a pas changé et l'affichage de données en lecture seule dans ce cas.