Obtenir que SqlBulkCopy respecte les noms de colonnes

c# sqlbulkcopy tsql

Question

Je suis en train de convertir certaines routines de génération de rapports basées sur des procédures stockées pour qu'elles s'exécutent en C #. L'idée générale est d'utiliser toutes les merveilles de C # / .NET Framework, puis de transférer les résultats dans la base de données. Tout se passe à merveille, à l'exception d'un problème que j'ai rencontré hier et résolu aujourd'hui.

Pour effectuer l'importation, je crée par programme un DataTable et utilise SqlBulkCopy pour déplacer les résultats sur le serveur.

par exemple

 DataTable detail = new DataTable();
 detail.Columns.Add(new DataColumn("Stock", Type.GetType("System.Decimal")));
 detail.Columns.Add(new DataColumn("Receipts", Type.GetType("System.Decimal")));
 detail.Columns.Add(new DataColumn("Orders", Type.GetType("System.Decimal")));

La table d'importation avait les champs dans l'ordre suivant.

...
Stock decimal(18,4),
Orders decimal(18,4),
Receipts decimal(18,4)
...

Essentiellement, la valeur de Receipts était affectée aux ordres, et inversement.

Evidemment, cela est dû au fait que SqlBulkCopy ne semble pas honorer le nom de colonne que je lui ai demandé de renseigner - il se contente de passer en position ordinale.

C'est un problème pour moi car nous utilisons SQL Compare de Redgate. Lors du transfert de modifications d'une base de données à une autre, la position ordinale des colonnes n'est pas nécessairement conservée. (Par exemple, si vous insérez une nouvelle colonne en tant que troisième champ ordinal, SQL Compare l'ajoutera simplement à la table lors d'une synchronisation, ce qui en fera la dernière colonne).

Cela gâche sérieusement ma solution. À présent, il ne s’agit que de tables «importées». Par conséquent, si besoin est, je peux les supprimer et les recréer dans le cadre d’un script de migration avec les positions ordinales intactes. Je préférerais ne pas le faire cependant.

Existe-t-il un moyen de forcer SqlBulkCopy à respecter les noms de colonne que vous lui indiquez de remplir?

Réponse acceptée

De http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.columnmappings.aspx :

Toutefois, si le nombre de colonnes diffère ou si les positions ordinales ne sont pas cohérentes, vous devez utiliser ColumnMappings pour vous assurer que les données sont copiées dans les colonnes appropriées.

Pour obtenir un exemple de code, voir "Mapping Columns" à l' adresse http://www.sqlteam.com/article/use-sqlbulkcopy-to-quickly-load-data-from-your-client-tossl


Réponse populaire

Voici une solution pour résoudre ce "bug".

La valeur par défaut est de mapper par ordinal / position.

Dans mon cas, je chargeais depuis une feuille de calcul avec des colonnes dans un ordre aléatoire. voici une solution rapide (table est mon DataTable qui est 'hors de l'ordre ordinal', et bulkCopy est l'objet SqLBulkCopy)

foreach (DataColumn col in table.Columns)
{
    bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
}

Comme vous pouvez le constater, je le force simplement à procéder à une nouvelle commande par nom, même si les noms sont IDENTIQUES.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi