2009-05-22 5 views
0

Hier, j'ai posé la question this question sur les meilleures pratiques pour un simple système de recherche documentaire sur lequel je commence à travailler.Comment gérer l'ajout programmé de champs?

Aujourd'hui, mon client m'a demandé s'il était possible de leur permettre d'ajouter des champs à l'entité principale à une date ultérieure en utilisant l'interface d'administration. C'est-à-dire que l'application vous permet de rechercher dans une table de base de données (appelons-la Entités), qui peut avoir diverses associations avec d'autres objets, mais l'accent est mis sur les Entités.

Maintenant, bien sûr, le ciel est la limite, et c'est possible.

Ma première pensée à ce problème est de créer deux nouvelles tables:

AdditionalFields (FieldID PK, FieldName, IsShownInSearchResults et autres métadonnées) C'est la table qui aurait ses lignes créées par l'interface d'administration. Par exemple, si le client décide ultérieurement d'ajouter la possibilité de suivre, par exemple, la couleur des yeux d'une Entité, il crée un champ AdditionalField avec un FieldName de "Couleur des yeux".

AdditionalFieldData (FieldDataID PK, EntityID FK, FieldID FK, FieldValue) Voici le tableau relatif aux entités aux leurs valeurs respectives pour tous les champs supplémentaires ajoutés par le client. Par exemple, avec notre exemple de couleur des yeux, si nous avons deux Entités (EntityID 3 et 4) au moment où le champ a été ajouté et le nouveau AdditionalField a un FieldID de 1, il est valide de ne pas avoir de données de couleur des yeux associées aux entités . Le client pourrait alors choisir, pour ajouter la couleur des yeux "Bleu" à l'entité 3, et nous insérerions une ligne à AdditionalFieldData comme ceci: (autogenerated PK, 3, 1, "Blue").

Puisque je veux rechercher facilement parmi ceux-ci, je demanderai simplement que tous les champs additionnels aient des valeurs de chaîne. Suite à l'approche que j'ai posté dans la question précédente, j'utiliserais Linq-To-SQL avec une requête similaire à la suivante pour la recherche d'informations lorsqu'un utilisateur effectue une recherche (bien sûr, la logique de filtrage sera: http://www.linq-to-sqlc.org/). plus complexe dans la pratique):

var results = from s in db.Stuff 
      where (s.Name.Contains(textFilter) || 
       s.Title.Contains(textFilter)) 
      select s; 

Je modifierais la requête pour ressembler à quelque chose comme ceci:

var results = from s in db.Stuff 
       where (...existing filter logic...) || 
        s.AdditionalFieldData.Any(afd => afd.FieldName.Contains(textFilter)) 
       select s; 

donc, ma question est: est-ce raisonnable? Y a-t-il une meilleure solution que j'ai manquée? Y a-t-il des implications de cette approche dont je devrais être conscient?

(S'il vous plaît pardonnez mes identifiants stupides, son début pour moi :)

Répondre

1

Je ne suis pas expert LINQ, mais d'un point de conception de base de données de vue ce que vous suggérez semble très bien pour moi. Une alternative que j'ai vu utilisé à quelques reprises est d'avoir tout un tas de champs 'spare' définis sur la table Entities, que les utilisateurs peuvent activer/désactiver via l'interface d'administration. Vous gagnez des performances de base de données de cette façon (en raison du nombre réduit de jointures), mais vous devez choisir à l'avance le nombre de champs de remplacement souhaités, et vous obtenez la plupart du temps de grandes tables vides.

Oh, et vous pouvez supposer que si vous choisissez d'ajouter N champs de rechange, vos utilisateurs veulent N + 1 ;-)

Questions connexes