2008-10-23 4 views
1

Modifier: J'utilise SqlDataAdapters pour remplir les ensembles de données. Désolé - j'aurais dû être plus clair.Mappage de DataSets fortement typés dans une méthode générique FillDataSet en C#?

Je travaille sur un projet où j'ai besoin de remplir un certain nombre d'ensembles de données fortement typés avec des informations provenant de procédures stockées. En ce moment, 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 est que je dois établir les correspondances entre les enregistrements renvoyés de la procédure stockée et les tables dans mes ensembles de données. Je suis venu avec deux options pour ce faire:

  • Ajouter un nouveau formel à ma méthode FillDataSet (KeyValuePair<string, string>[] mappings) qui fournirait les informations pour les applications de table.
  • Créez un DataSetMappingFactory qui prendra un DataSet en tant que paramètre, puis ajoutera les mappages appropriés en fonction de son type. Si c'était un type inconnu, alors il n'ajouterait aucun mappage. Ensuite, il renvoie la DataSet à la méthode FillDataSet.

Est-ce que quelqu'un parmi vous a d'autres idées sur la façon dont je pourrais aborder ce problème? Aussi, est-ce que quelqu'un veut peser sur une approche qui serait la meilleure en termes de conception orientée objet?

+0

Quel mécanisme utilisez-vous pour remplir les différents DataTables? Un DataReader? TableAdapters? Autre chose? –

+0

J'utilise SqlDataAdapters. J'ai mis à jour la question pour que ce soit clair. :) –

Répondre

1

La première question que je voudrais poser est: ai-je vraiment besoin de faire cela du tout? Le concepteur DataSet typé vous donne 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 avez déjà une méthode Fill pour chaque DataTable. Est-ce logique de réinventer cette roue?

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

Dans ce cas, il me semble que votre objectif est de pouvoir remplir un DataSet à partir d'une série de procédures stockées avec un code qui en sait le moins possible sur les détails d'implémentation. C'est donc un processus qui va être piloté par des métadonnées. Lorsque vous avez un processus piloté par des métadonnées, ce qui vous importe le plus à long terme, c'est combien il sera facile de gérer les métadonnées utilisées par le processus. Une fois que le code fonctionnera, vous ne le toucherez probablement pas beaucoup. Mais vous allez peaufiner les métadonnées en permanence.

Si je regarde le problème de ce point de vue, la première chose que je pense faire est de concevoir un DataSet typé pour contenir les métadonnées. Cela nous donne un tas de choses que nous avions autrement à comprendre:

  • un format de persistance
  • un chemin facile à construire une interface utilisateur liée
  • un chemin tout aussi simple à la persistance des métadonnées dans un base de données si nous décidons de descendre cette route
  • un modèle d'objet pour la navigation des données.

Dans ce DataSet, vous disposez d'une table DataSetType, indexée sur le Type de chaque DataSet typé que vous avez l'intention de renseigner. Il aurait une table StoredProcedures enfant, avec une ligne pour chaque SP appelé. Cela aurait deux tables enfants, Parameter et DataTableType. Il y aurait une rangée DataTableType, ordonnée par position ordinale, pour chaque ensemble de résultats que le SP devrait retourner. La table DataTableType aurait une table ColumnMapping enfant. C'est dans cette table que vous gérez les mappages entre les colonnes du jeu de résultats et les colonnes de la table que vous remplissez. Assurez-vous que toutes vos DataRelations sont imbriquées et que vous avez donné 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 au DataSet de métadonnées, la connexion, etc ,, et il expose une méthode avec cette signature.

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

Vous commencez en utilisant le type de l'targetDs pour trouver la ligne de DataSetType haut niveau. 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 classe, de sorte que, lors de l'exécution de l'opération, elle peut déclencher des événements pour que l'application appelante sache comment elle progresse.

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

+0

Ceci est une approche très intéressante pour résoudre mon problème. Je ne suis pas sûr si je vais l'utiliser en raison de la surcharge qu'il ajouterait à mon projet, mais j'aime que l'information serait pilotée par les ensembles de données. –

+0

Si vous devez persister vos métadonnées, et/ou si vous souhaitez pouvoir les modifier sans reconstruire/redéployer votre logiciel, les frais généraux semblent soudainement minimes. –

Questions connexes