Question

Modifier: J'utilise SqlDataAdapters pour remplir les ensembles de données. Désolé, j'aurais dû être plus clair.

Je travaille sur un projet dans lequel je dois remplir un certain nombre d'ensembles de données fortement typés avec des informations provenant de procédures stockées. À l'heure actuelle, j'ai une méthode générique dans ma couche d'accès aux données:

public static DataSet FillDataSet(DataSet dataSet, string storedProcedureName, Dictionary<string, string> parameters);

Le problème, c’est que j’ai besoin d’établir des correspondances entre les jeux d’enregistrements renvoyés à partir de la procédure stockée et les tables de mes ensembles de données. J'ai proposé deux options pour cela:

  • Ajouter un nouveau formel à ma FillDataSet méthode (KeyValuePair<string, string>[] mappings) fournissant les informations pour les mappages de table.
  • Créez un DataSetMappingFactory qui prendrait un DataSet en tant que paramètre, puis ajoutez les mappages appropriés en fonction de son type. S'il s'agissait d'un type inconnu, il n'y aurait alors aucun mappage. Ensuite, il renverrait la DataSet méthode <=>.

Quelqu'un parmi vous a-t-il d'autres idées sur la façon dont je pourrais aborder ce problème? De plus, est-ce que quelqu'un souhaite se prononcer sur une approche qui serait la meilleure en termes de conception orientée objet?

Était-ce utile?

La solution

La première question que je poserais est la suivante: dois-je vraiment faire cela du tout? Le concepteur DataSet typé vous fournit déjà un outil pour définir le mappage entre une procédure stockée et un DataTable. Si vous concevez votre DataSet avec soin, vous disposez déjà d'une méthode de remplissage pour chaque DataTable. Est-il judicieux de réinventer cette roue?

Je pense que ça pourrait. C'est vraiment bien qu'il y ait un moyen de maintenir cette correspondance, mais tout dans cette correspondance est gelé au moment de la compilation. Si vous souhaitez modifier le mappage, vous devez reconstruire votre assembly. De plus, la conception typée DataSet ne traite pas les procédures stockées qui renvoient plusieurs ensembles de résultats. Si vous souhaitez mapper de manière générique les paramètres et les valeurs, vous devez utiliser la réflexion pour obtenir les listes d'arguments à partir des méthodes Fill. Il se peut que, si vous examinez ces facteurs (et d’autres auxquels je ne pense pas), travailler avec l’outil existant ne soit pas la solution.

Dans ce cas, il me semble que votre objectif est de pouvoir renseigner un ensemble de données à partir d'une série de procédures stockées avec un code qui en sait le moins possible sur les détails de la mise en œuvre. Il s’agit donc d’un processus qui reposera sur les métadonnées. Lorsque vous avez un processus basé sur des métadonnées, ce qui compte le plus pour vous à long terme, c'est la facilité avec laquelle vous pourrez conserver les métadonnées utilisées par le processus. Une fois que le code fonctionne, vous ne le toucherez probablement pas beaucoup. Mais vous peaufinerez constamment les métadonnées.

Si je considère le problème sous cet angle, la première chose à faire est de concevoir un DataSet typé pour contenir les métadonnées. Cela nous donne un tas de choses que nous aurions autrement à comprendre:

  • un format de persistance
  • un chemin simple pour créer une interface utilisateur liée
  • un chemin tout aussi simple pour conserver les métadonnées dans une base de données si nous décidons de suivre cette voie
  • un modèle objet pour naviguer dans les données.

Dans ce DataSet, vous auriez une table DataSetType, saisie sur le type de chaque DataSet typé que vous souhaitez pouvoir renseigner. Il y aurait une table enfant StoredProcedures, avec une ligne pour chaque SP appelé. Cela aurait deux tables enfants, Parameter et DataTableType. Il y aurait une ligne DataTableType, classée par position ordinale, pour chaque ensemble de résultats que le SP devrait renvoyer. La table DataTableType aurait une table ColumnMapping enfant. C'est dans cette table que vous souhaitez conserver les correspondances entre les colonnes du jeu de résultats et les colonnes de la table que vous remplissez.

Assurez-vous que toutes vos relations de données sont imbriquées et que vous avez attribué des noms rationnels aux relations. (J'aime FK_childtablename_parenttablename.)

Une fois que vous avez cela, la conception de la classe devient assez simple. La classe a une référence aux métadonnées DataSet, la connexion, etc., et expose une méthode avec cette signature:

public void FillDataSet(DataSet targetDs, Dictionary<string, Dictionary<string, KeyValuePair<string, string>> parameterMap);

Vous commencez par utiliser le type de targetDs pour rechercher la ligne DataSetType de niveau supérieur. Ensuite, toutes les méthodes privées parcourent les listes de DataRows renvoyées par DataTable.GetChildRows (). Et vous ajoutez un ou deux événements à la conception de la classe afin qu’elle puisse, au fur et à mesure de ses opérations, déclencher des événements pour permettre à l’appelant appelant de suivre son évolution.

Probablement le premier endroit où je souhaiterais remanier cette conception est de me donner un contrôle plus fin du processus de remplissage. Par exemple, comme prévu, il n'y a qu'un seul ensemble de SP par DataSet typé. Et si je veux seulement remplir un sous-ensemble du DataSet? Comme prévu, je ne peux pas. Mais vous pouvez facilement faire la clé primaire de la table DataSetType en deux parties, les parties étant le type DataSet et une clé de chaîne (avec un nom comme SPSetName ou OperationName) et ajouter la seconde partie de la clé à la liste d'arguments FillDataSet. .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top