SQL Bulkcopy YYYYMMDD problema

c# date sqlbulkcopy

Pregunta

Tengo un problema de conversión de Cadena a fecha al usar SQL Bulkcopy en asp.net 3.5 con C #

Leí un archivo CSV grande (con lector CSV ). Una de las cadenas de lectura debe cargarse en una columna de fecha del servidor SQL 2008.

Si el archivo de texto contiene, por ejemplo, la cadena '2010-12-31', SQL Bulkcopy lo carga sin ningún problema en la columna Fecha.

Sin embargo, si la cadena es '20101231', aparece un error:
El valor dado de tipo Cadena del origen de datos no se puede convertir a la fecha de tipo de la columna de destino especificada

El archivo contiene 80 millones de registros, por lo que no puedo crear un archivo de datos ...

SqlBulkcopy Columnmappings etc. están todos bien. También cambiar a DateTime no ayuda.

Lo intenté

SET DATEFORMAT ymd;

Pero eso no ayuda.

¿Alguna idea de cómo decirle a SQL Server que acepte este formato? De lo contrario, crearé una solución personalizada en el lector CSV pero preferiría algo en SQL.

Actualización Siguiendo con las dos respuestas, estoy usando una copia masiva de SQL como esta (como se propuso en Stackoverflow en otra pregunta):

El lector CSV (ver el enlace anterior en el proyecto de código) devuelve valores de cadena (no es de tipo fuerte). El CSVreader implementa System.Data.IDataReader para que pueda hacer algo como esto:

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

Todos los campos provenientes del iDataReader son cadenas, por lo que no puedo usar el enfoque de c # a menos que cambie un poco en el CSVreader

Por lo tanto, mi pregunta no está relacionada con cómo solucionarlo en C #, puedo hacerlo pero quiero evitarlo.

Es extraño, porque si haces un sql algo como

 update set [somedatefield] = '20101231' 

También funciona, pero no con bulkcopy.

¿Alguna idea de por qué?

Gracias por cualquier consejo, Pleun

Respuesta aceptada

Si puede entregarlo en C #, entonces este código ayudará a obtener la fecha en la cadena como un objeto DateTime que puede pasar directamente

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

Si desea que se formatee como cadena, entonces:

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

Buena suerte.

Actualizar

En su escenario, no sé por qué la fecha no se formatea automáticamente, pero desde C # debe ingresar e interferir en el proceso de pasar los datos al método WriteToServer() . Lo mejor que puedo hacer (teniendo en cuenta el rendimiento) es tener un caché de elementos de DataRow y pasarlos al método WriteToServer () . Solo escribiré el código de muestra en 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);
}

No es un código completo, pero creo que puedes resolverlo ...


Respuesta popular

Tema más antiguo, pero quería agregar un enfoque alternativo.

Tuve el mismo problema con SQLBulkLoader al no permitir las especificaciones DataType / culture para las columnas cuando se transmite desde IDataReader.

Para reducir la sobrecarga de velocidad de la construcción de datarows localmente y en lugar de que el análisis se produzca en el objetivo, un método simple que utilicé fue establecer temporalmente la cultura del hilo en la cultura que define el formato en uso, en este caso para las fechas en formato de EE. UU. .

Para mi problema, las fechas en-US en la entrada (en Powershell):

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

Para su problema, podría hacer lo mismo, pero dado que el formato de fecha no es específico de la cultura, cree un objeto de cultura predeterminado (no probado):

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

Descubrí que permitir que el servidor de la base de datos realice las conversiones de tipo una vez que hayan pasado a través de la interfaz SQLBulkCopy sea considerablemente más rápido que realizar el análisis localmente, particularmente en un lenguaje de scripting.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué