Un moyen pratique de stocker une quantité «raisonnablement importante» de données qui ne change presque jamais?

13

Pensez en termes de tables de recherche pré-calculées ou quelque chose. À quel moment est-il plus judicieux d'utiliser une base de données au lieu de valeurs de codage en dur dans mon application? Les valeurs ne changeront pas et elles sont bien séparées des développeurs de maintenance. 100 valeurs, 1k, 10k, 100k? Je veux stocker environ 40k valeurs. En ce moment, c'est une switchdéclaration générée par la machine (dont VS2010 n'est pas satisfait).

Éditer:

Si quelqu'un est curieux, voici comment je l'ai abordé: mes données étaient stockables dans deux tableaux flottants de 100k éléments, c'est donc ce que j'ai fait. Il a fallu environ 20 secondes pour générer les données, alors je l'ai fait une fois et sérialisé en une ressource intégrée avec un BinaryFormatter. Le décompactage des données prend environ 5 millisecondes au démarrage de l'application et surpasse de près de 45 000x la mise en œuvre de la base de données que je remplaçais (ces valeurs codées en dur auparavant).

Bryan Boettcher
la source

Réponses:

5

Ma suggestion est de conserver les données dans un fichier ou une table de base de données. Si la vitesse n'est pas un problème, alors interrogez le fichier ou la base de données (la base de données est meilleure) au moment de l'exécution. Si la mémoire n'est pas un problème, mais que vous souhaitez une certaine vitesse, chargez les données en mémoire au démarrage du programme. En C #, vous pouvez utiliser et tableau, lister ou (meilleure option) une table de hachage et avoir une méthode pour renvoyer les données dont vous avez besoin lors de l'exécution (ie getDataValue (string keyToValue)).

Je vous recommande de ne pas utiliser l'instruction switch car elle serait très difficile à maintenir et entraînerait une empreinte exe importante.

Table de hachage, par exemple http://support.microsoft.com/kb/309357

adam f
la source
C'est finalement ce que j'ai fait: consultez mon article mis à jour.
Bryan Boettcher
1
+1 pour la suggestion de base de données. Les bases de données sont conçues pour stocker de gros volumes de données et vous permettent de les récupérer très rapidement.
NoChance
Voir stackoverflow.com/questions/301371/… pour savoir pourquoi il vaut mieux utiliser un dictionnaire pour cela plutôt qu'une table de hachage. YMMV
Chris McKee
6

Personnellement, je suis d'accord pour stocker n'importe quelle quantité de données, codées en dur dans l'application, jusqu'à ce qu'il ne soit pas nécessaire de les modifier pour un déploiement ou un correctif particulier.

Cependant, le stockage et l'accès aux données à l'aide de l'instruction switch C #, est plutôt une mauvaise pratique, car dans les couples étroitement stockés et modèle d'accès aux données et implique une seule méthode d'accès à la méthode (par paramètre de commutateur).

Je préférerais stocker les données dans une table de hachage ou un dictionnaire, et fournir des classes distinctes pour récupérer les données, et remplir une seule fois des dictionnaires de recherche.

Récemment, j'ai trouvé assez pratique d'implémenter un petit DSL pour spécifier des règles métier ( interface fluide pour SiteMap ou méthode de vérification des questions d'entretien de calculatrice fiscale "calc" pour la défenition des règles), puis de fournir un objet séparé pour interroger ces règles. Cette technique s'appliquerait bien pour le scénario de cas de commutation.

L'un des avantages de cette décomposition est que vous pouvez implémenter un certain nombre de vues sur vos données, sans toucher au blob de lignes XXXk, qui définit ces données.

Valera Kolupaev
la source
J'ai étendu la réponse avec quelques exemples.
Valera Kolupaev
2

Une déclaration de commutateur de ligne 40k est un peu discutable. Je suppose que vous devez toujours effectuer des opérations de requête, n'est-ce pas? Avez-vous essayé d'encapsuler les données? Utilisez ensuite LINQ pour effectuer des opérations de requête sur la collection pour tester les performances. Obtenez des temps concrets en exécutant des tests unitaires avec une minuterie comme StopWatch . Ensuite, si vous pensez que cela pourrait bien fonctionner. Vérifiez si les performances sont acceptables pour les utilisateurs.

P.Brian.Mackey
la source
2

J'ai eu une exigence comme celle-ci deux fois. Les applications ont été conçues pour être autonomes sans configuration / accès à la base de données requis. Dans les deux cas, j'ai utilisé des fichiers XML pour stocker les données. Dans le premier, qui était sur le Framework 2.0, j'ai utilisé les appels d'analyse XML à l'ancienne pour rechercher des données. Pour la plus récente, sur le Framework 3.5, j'ai utilisé LINQ to XML pour trouver ce dont j'avais besoin. Dans les deux cas, l'accès aux données a été encapsulé dans des classes.

jfrankcarr
la source
1

L'essentiel ici est de vous assurer que votre interface publique encapsule votre implémentation, mais ce n'est pas votre question et il n'y a aucune raison de penser que vous ne l'avez pas fait. Au-delà de cela, c'est juste une question de performance vs chagrin (et les différences de performance peuvent ne pas valoir la peine d'être prises en compte). Comme solution pratique, pour le problème VS 2010, vous pouvez toujours diviser la déclaration de cas en une hiérarchie de déclarations de cas - le niveau supérieur pourrait appeler l'une des 10 autres méthodes, chacune avec une déclaration de cas de 4000 cas, par exemple. Vous pourriez mettre chacun des 10 dans son propre fichier si vous le deviez. Un peu moche, mais vous générez quand même du code.

En ce qui concerne le nombre de passer à une base de données -it juste chaque fois que ne pas utiliser une base de données devient un problème.

psr
la source
J'apprécie l'idée que mon interface encapsule l'implémentation: c'est certainement le cas. La fonctionnalité est exposée via une GetValuesForInputméthode de type, et ma déclaration massive est cachée dans l'implémentation.
Bryan Boettcher
1

Vous pouvez utiliser quelque chose comme SQL Compact. Mettez les données dans une table et laissez le fichier DB dans le projet. Les tableaux sont mieux adaptés à cette quantité de données qu'une instruction switch.

Morgan Herlocker
la source
1

Je pense que le mot clé ici est «à peine»

Si les données ne changent jamais - par exemple, des valeurs mathamatiques précalculées, des constantes de couleur, etc. - alors assurez-vous, tant que la taille est gérable pour vous, conservez-la dans le code. Sachez simplement que si les performances posent problème, les instructions case / switch seront très lentes par rapport aux autres options.

Si les données ne changent presque jamais - par exemple, les indicatifs régionaux, les frontières nationales, etc. - je chercherais probablement à conserver les données à l'extérieur d'une manière ou d'une autre. Surtout si cela commençait à devenir plus de deux douzaines de valeurs.

GrandmasterB
la source
1
Cela dépend de la qualité du compilateur. Une déclaration de cas dans Delphi peut être extrêmement efficace.
Loren Pechtel
1

Si vous stockez de gros volumes de données dans votre application, votre programme peut se charger plus lentement et vous risquez d'exposer le code au cas où quelqu'un pourrait jouer avec les binaires ou l'exécutable.

De plus, si le programme est édité plusieurs fois, qui sait, vous pourriez introduire des erreurs en tapant des nombres par erreur ou à la suite d'une commande de changement.

Peut-être qu'à l'avenir, quelqu'un demandera d'exécuter des requêtes sur les données, par exemple, quelqu'un peut demander la moyenne d'une colonne, auquel cas vous devrez modifier votre application et ajouter une méthode pour calculer chaque requête que votre utilisateur pose. avec, puis suivez toutes les étapes pour promouvoir votre code en production. Ce n'est vraiment pas bon.

La séparation des données et du code est une bonne pratique, surtout si les données sont volumineuses.

Aucune chance
la source