2013-07-24 3 views
0

J'ai un programme où l'utilisateur aura l'option de mapper une variété de sources de données avec un schéma de colonne imprévisible. Donc, ils peuvent avoir une base de données SQL Server avec 10 champs ou un fichier Excel avec 20 - les noms peuvent être quelque chose et les types de données des champs peuvent être un mélange de texte et numérique, dates, etc.NET Convertir le contenu d'un DataTable en un autre DataTable avec un schéma différent

L'utilisateur a alors pour fournir une cartographie de ce que chaque champ signifie. La colonne 4 est un "LocName", la colonne 2 est un "LocX", la colonne 1 est un "LocDate", etc. Les noms et les types de données que l'utilisateur présente comme options sont bien définis par DataSet DataTable (Fichier xchema XSD).

Par exemple, si la source contient des données formatées comme ceci:

User Column 1: "LocationDate" of type string 
User Column 2: "XCoord" of type string 
User Column 3: "YCoord" of type string 
User Column 4: "LocationName" of type int 

et l'utilisateur fournit une cartographie qui exigerait que traduit ce pour la application nécessaire DataTable:

Application Column "LocName" of type string = Column **4** of user table 
Application Column "LocX" of type double  = Column **2** of user table 
Application Column "LocY" of type double  = Column **3** of user table 
Application Column "LocDate" of type datetime = Column **1** of user table 

J'ai des routines qui se connectent à la source et extraient les données pour une requête d'utilisateur au format "brut" en tant que DataTable - donc cela prend le schéma de la source. Ma question est la suivante: quelle est la meilleure façon de "transformer" les données du DataTable brut en données DataTable requises dans la mienne pour que cette projection prenne en compte les conversions de type? Un foreach fonctionnera évidemment mais cela semble être une force brute puisqu'il devra tenir compte des types de données avec chaque boucle sur chaque ligne. Est-ce le moyen le plus simple de le faire avec LINQ ou ADO.NET?

Répondre

0

Je ferais normalement dans select qui ressemble à la table de destination, mais avec des données de la table source. Vous devez également appliquer les conversions de données selon les besoins.

Select 
    Cast (LocationNameLocationName As varChar(...) As LocName 
, LocX As XCoord 
, ... 
From SourceTable 

Difficile à décrire dans une réponse simple. ce que j'ai fait dans le passé est une requête "vide" comme "Select * From sourcetable Where 1 = 0" qui ne renvoie aucune ligne mais rend toutes les colonnes et leurs types disponibles dans le jeu de résultats. Vous pouvez parcourir les objets ADO de la colonne pour obtenir le type de chacun. Vous pouvez ensuite utiliser cette information pour créer dynamiquement une véritable instruction SQL avec les conversions.

Vous avez encore beaucoup de logique pour décider de la conversion, mais ils se produisent tous lors de la création de l'instruction, et non lors de la lecture de la table. Vous devez toujours dire dans le code "si la colonne source est Integer et la colonne de destination est un caractère, alors je veux générer dans la sélection", Cast (comme Varchar) '"

Lorsque vous avez terminé la construction du texte de la sélectionnez, vous avez une sélection, vous pouvez exécuter dans ADO pour obtenir les lignes et le mouvement réel devient aussi simple que de lire/écrire avec le champ entrant comme vous le souhaitez. Vous pouvez également utiliser cette option pour sélectionner "Insérer dans Sélectionner ...".

Espérons que cela a du sens. Le concept est plus facile à faire qu'à décrire.

+0

Merci pour la publication. Comment traiteriez-vous le fait que le DataType de la source peut être quelque chose à l'exécution? – Ernie

+0

Voir les modifications apportées à la réponse originale. – asantaballa

+0

Merci encore. Ok, c'est un peu ce que je pensais. J'espérais une sorte de "magie" de la part de LINQ ou autre chose à laquelle je n'avais pas pensé mais je suppose que c'était plus un vœu pieux - il ne peut pas faire tout le monde pour moi je suppose. :) – Ernie