/ / Chiedere a SqlBulkCopy di onorare i nomi delle colonne - c #, tsql, sqlbulkcopy

Ottenere SqlBulkCopy per onorare i nomi delle colonne - c #, tsql, sqlbulkcopy

Sono in procinto di convertire alcuni memorizzatiroutine di reporting basate su procedure da eseguire in C #. L'idea generale è quella di utilizzare tutte le meraviglie di C # /. NET Framework e poi rimandare i risultati nel DB. Tutto sta andando a gonfie vele, tranne un problema che ho riscontrato ieri e risolto oggi.

Per eseguire l'importazione, sto "creando a livello di programmazione una DataTable e utilizzando SqlBulkCopy per spostare i risultati sul server.

per esempio.

 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 tabella di importazione aveva i campi nel seguente ordine.

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

In sostanza, il valore di Entrate stava andando in Ordini e viceversa.

Evidentemente, questo è perché SqlBulkCopy non sembra onorare il nome della colonna che gli ho detto di popolare - va solo per posizione ordinale.

Questo è un problema per me poiché usiamo l'SQL di RedgateConfrontare. Quando si trasferiscono le modifiche da un database a un altro, la posizione ordinale delle colonne non viene necessariamente mantenuta (ad es. Se si inserisce una nuova colonna come terzo campo ordinale, SQL Compare la aggiungerà semplicemente alla tabella su una sincronizzazione, rendendola la ultima colonna).

Questo seriamente incasina la mia soluzione. Ora, queste sono solo tabelle "import", quindi se necessario, posso rilasciarle e ricrearle come parte di qualsiasi script di migrazione con le posizioni ordinali intatte. Preferirei non farlo.

C'è un modo per forzare SqlBulkCopy a onorare i nomi delle colonne che gli dici di riempire?

risposte:

15 per risposta № 1

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

Tuttavia, se i conteggi delle colonne differiscono o le posizioni ordinali no coerente, è necessario utilizzare ColumnMappings per assicurarsi che i dati lo siano copiato nelle colonne corrette.

Per il codice di esempio, consultare "Mapping Columns" all'indirizzo http://www.sqlteam.com/article/use-sqlbulkcopy-to-quickly-load-data-from-your-client-to-sql-server


15 per risposta № 2

Ecco una soluzione per risolvere questo "bug".

L'impostazione predefinita è mappare per ordinale / posizione.

Nel mio caso stavo caricando da un foglio di calcolo con colonne in ordine casuale. qui è una soluzione rapida (la tabella è la mia DataTable che è "fuori dall'ordine ordinario" e bulkCopy è l'oggetto SqLBulkCopy)

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

Come puoi vedere, lo sto solo forzando a riordinare per nome, anche se i nomi sono IDENTICI.


1 per risposta № 3

C'è un'opzione in SQL Compare to Force ColumnOrdina nelle opzioni del progetto. Questo genererà uno script che riordinerà le colonne. Potrei sbagliarmi, ma penso che questa operazione potrebbe richiedere la ricostruzione della tabella, quindi si prega di usare con cautela in quanto ciò potrebbe influire sulle prestazioni. Lo script, tuttavia, manterrà i dati della tabella.


0 per risposta № 4

Vi sono sovraccarichi che consentono di specificare la posizione ordinale o il nome della colonna di origine da mappare sulla colonna di destinazione.

Check-out SqlBulkCopyColumnMappingCollection.Add e impostare il SqlBulkCopy.ColumnMappings proprietà.


0 per risposta № 5

Potrei mancare qualcosa, ma perché non potresti cambiare l'ordine delle tue colonne? Di solito non costruisco il mio DataTable a mano. Io uso il FillSchema metodo di SqlDataAdapter, usare un "select * from targetTable" query. Quindi sono sempre sicuro che il mio DataTablesi adatta alla tabella di destinazione.


0 per risposta № 6

Ecco un "Gist" con un metodo di estensione per questo.

Esempio:

bulkCopy
.WithColumnMappings(table.Columns)
.WriteToServer(table);

Questo cancella i mapping delle colonne esistenti, quindi aggiunge un mapping per ogni colonna passata.


0 per risposta № 7

Un modo semplice di implementare la mappatura delle colonne in copia bulk, assicurati che i nomi delle tue colonne databili siano esattamente gli stessi della tabella in cui vuoi scaricare tutti i dati

using (SqlBulkCopy bulkcopy = new SqlBulkCopy(dc.ConnectionString))
{
bulkcopy.BulkCopyTimeout = 150;

// column mapping defined
dt.Columns.Cast<DataColumn>().ToList().ForEach(f =>
{
SqlBulkCopyColumnMapping bccm = new SqlBulkCopyColumnMapping();
bccm.DestinationColumn = f.ColumnName;
bccm.SourceColumn = f.ColumnName;
bulkcopy.ColumnMappings.Add(bccm);
});
// column mapping defined

bulkcopy.DestinationTableName = outputTable;
bulkcopy.WriteToServer(dt);

}