System is thrown by SqlBulkCopy. When using WriteToServer, a FormatException occurs (DataTable)

c# csv formatexception sql sqlbulkcopy


A technique to read data from a CSV file and import it into a SQL table is currently being written by me.

        DataTable dt = new DataTable();
        String line = null;
        int i = 0;

        while ((line = reader.ReadLine()) != null)
            String[] data = line.Split(',');
            if (data.Length > 0)
                if (i == 0)
                    foreach (object item in data)
                        DataColumn c = new DataColumn(Convert.ToString(item));
                        if (Convert.ToString(item).Contains("DATE"))
                            c.DataType = System.Type.GetType("System.DateTime");
                        else { c.DataType = System.Type.GetType("System.String"); }
                    DataRow row = dt.NewRow();
                    for (int j = 0; j < data.Length; j++)
                        if (dt.Columns[j].DataType == System.Type.GetType("System.DateTime"))
                            row[j] = Convert.ToDateTime(data[j]);
                            row[j] = data[j];
        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings[Constant.CONNECTION_STRING_NAME].ConnectionString);
        SqlBulkCopy s = new SqlBulkCopy(con);
        s.DestinationTableName = "abc";

The issue is that s.WriteToServer(dt) always causes an Exception to be issued, which says

System. The string was not recognized as a valid DateTime, leading to a FormatException. Starting at index 0, there is an unidentified word.

The data were appropriately imported into the DataTable after I performed some debugging. This is an example of a data row from my CSV file.

V01,,22097,ABCD01,Physical Activity,10/01/2010,Entertain Kiosk,ABCD - EFG 54,30,,AB01,W1234567891,,08/07/2006,100

and my SQL table structure

RowID   int Unique/AutoIncrement
DataVendorId    varchar(32) 
DataVendorSubId varchar(32) 
DataVendorClientId  varchar(32) 
DataVendorActivityCode  varchar(32) 
ActivityName    varchar(64) 
EffectiveDate   datetime    
ActivityLevel1  varchar(253)    
ActivityLevel2  varchar(253)    
ActivityLevel3  varchar(253)    
ActivityLevel4  varchar(253)    
ActivityLevel5  varchar(253)    
ParticipantID   varchar(32) 
DataVendorAltId varchar(32) 
FileCreationDate    datetime    
IncValue    varchar(5)  
CreatedDate datetime    optional/allow null
ModifiedDate    datetime    optional/allow null
11/12/2010 6:24:15 AM

Accepted Answer

The first issue I notice is that you'll have issues with theRowID column; I anticipate that it is now attempting to offset your data by one column since you are ignoring it. You may either play about with the mappings or add a column to your data table.RowID column (at index 0), however take aware that unless you allow identity-insert, SQL Server will disregard the data.

Consider using a more precise date-to-time conversion:

row[j] = DateTime.ParseExact(data[j], "dd/MM/yyyy", CultureInfo.InvariantCulture);

You may need to adjust it since I can't determine from the data if that is dd/MM or MM/dd.

11/12/2010 6:34:36 AM

Popular Answer

When I created the mapping, I was able to fix a similar issue where the columns were incorrect:

using (SqlBulkCopy sbc = new SqlBulkCopy(ConfigurationManager.ConnectionStrings["SQLDatabase"].ConnectionString, SqlBulkCopyOptions.KeepIdentity))
                sbc.DestinationTableName = "DestinationTable";
                sbc.ColumnMappings.Add("foo", "bar");
                sbc.ColumnMappings.Add("hello", "world");
                sbc.ColumnMappings.Add("col1", "col2");

In order to convert my List, I also have a List to DataTable converter extension that I utilize.

public static DataTable ToDataTable<T>(this IEnumerable<T> data)
            PropertyDescriptorCollection properties =
            DataTable table = new DataTable();
            foreach (PropertyDescriptor prop in properties)
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
            foreach (T item in data)
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                    row[prop.Name] = GetDataValue(prop.GetValue(item));
            return table;

My data is cleaned up for MinValue dates, etc., using the GetDataValue() method:

private static object GetDataValue(object value)
            if (value == null || (value.GetType() == typeof(DateTime) && Convert.ToDateTime(value) == DateTime.MinValue) || (value.GetType() == typeof(DateTime) && Convert.ToDateTime(value) < Convert.ToDateTime("01/01/1753")))
                return DBNull.Value;

            return value;

Related Questions

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow