SQL Bulkcopy YYYYMMDD problema

c# date sqlbulkcopy

Domanda

Ho un problema di conversione da stringa a data usando SQL Bulkcopy in asp.net 3.5 con C #

Ho letto un file CSV di grandi dimensioni (con lettore CSV ). Una delle stringhe leggere dovrebbe essere caricata in una colonna Data 2008 server SQL.

Se il file di testo contiene ad esempio la stringa "2010-12-31", SQL Bulkcopy lo carica senza problemi nella colonna Data.

Tuttavia, se la stringa è '20101231', viene visualizzato un errore:
Il valore dato di tipo String dall'origine dati non può essere convertito in data tipo della colonna di destinazione specificata

Il file contiene 80 milioni di record, quindi non posso creare un datatable ....

SqlBulkcopy Columnmappings ecc. Sono tutti ok. Anche il passaggio a DateTime non aiuta.

Provai

SET DATEFORMAT ymd;

Ma questo non aiuta.

Qualche idea su come dire a SQL Server di accettare questo formato? Altrimenti creerò una correzione personalizzata nel lettore CSV ma preferirei qualcosa in SQL.

aggiornamento Seguendo le due risposte, sto usando SQL bulkcopy come questo (come proposto su Stackoverflow in un'altra domanda):

Il lettore CSV (vedere il link sopra in codeproject) restituisce valori stringa (non fortemente digitati). CSVreader implementa System.Data.IDataReader in modo che io possa fare qualcosa del genere:

using (CsvReader reader = new CsvReader(path)) 
using (SqlBulkCopy bcp = new SqlBulkCopy(CONNECTION_STRING))
{ bcp.DestinationTableName = "SomeTable"; 
  // columnmappings
  bcp.WriteToServer(reader); } 

Tutti i campi provenienti da iDataReader sono stringhe, quindi non posso usare l'approccio c # a meno che non cambi abbastanza nel CSVreader

La mia domanda non è quindi correlata su come risolverlo in C #, posso farlo ma voglio impedirlo.

È strano, perché se fai un in sql qualcosa del genere

 update set [somedatefield] = '20101231' 

funziona anche, ma non con bulkcopy.

Qualche idea del perché?

Grazie per qualsiasi consiglio, Pleun

Risposta accettata

Se puoi farlo in C #, allora questo codice ti aiuterà a ottenere la data nella stringa come un oggetto DateTime che puoi passare direttamente

//datestring is the string read from CSV
DateTime thedate = DateTime.ParseExact(dateString, "yyyyMMdd", null);

Se vuoi che sia formattato come stringa, allora:

string thedate = DateTime.ParseExact(dateString, "yyyyMMdd", null).ToString("yyyy-MM-dd");

In bocca al lupo.

Aggiornare

Nel tuo scenario non so perché la data non è formattata automaticamente ma da C # è necessario entrare e interferire nel processo di trasmissione dei dati al metodo WriteToServer() . La cosa migliore che penso si possa fare (tenendo presente la Performance) è avere una cache di oggetti DataRow e passarli al metodo WriteToServer () . Scriverò il codice di esempio in un minuto ...

//A sample code.. polish it before implementation
//A counter to track num of records read
long records_read = 0;
While(reader.Read())
{
    //We will take rows in a Buffer of 50 records
    int i = records_read;//initialize it with the num of records last read
    DataRow[] buffered_rows = new DataRow[50];
    for(;i<50 ;i++)
    {
        //Code to initialize each rows with the data in the reader
        //.....
        //Fill the column data with Date properly formatted
        records_read++;
        reader.Read();
    }
    bcp.WriteToServer(buffered_rows);
}

Il suo codice non è completo, ma penso che tu possa risolverlo ...


Risposta popolare

Problema precedente, ma volevo aggiungere un approccio alternativo.

Ho avuto lo stesso problema con SQLBulkLoader che non consente le specifiche DataType / cultura per le colonne durante lo streaming da IDataReader.

Per ridurre la velocità di overhead della costruzione di datarows localmente e invece l'analisi si verifica sul target, un metodo semplice che ho usato è stato quello di impostare temporaneamente la cultura del thread sulla cultura che definisce il formato in uso - in questo caso per le date in formato USA .

Per il mio problema - date in-USA nell'input (in PowerShell):

[System.Threading.Thread]::CurrentThread.CurrentCulture = 'en-US'
<call SQLBulkCopy>

Per il tuo problema, potresti fare lo stesso, ma poiché il formato della data non è specifico per la cultura, crea un oggetto cultura predefinito (non testato):

CultureInfo newCulture = (CultureInfo) System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
newCulture.DateTimeFormat.ShortDatePattern = "yyyyMMDD;
Thread.CurrentThread.CurrentCulture = newCulture;

Ho scoperto che consentire al server di database di eseguire le conversioni di tipo una volta che hanno ottenuto l'interfaccia SQLBulkCopy per essere notevolmente più veloce rispetto all'analisi locale, in particolare in un linguaggio di scripting.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow