Reputation: 408
I was wondering if someone could help. I am attempting to read a CSV file in C# and import it's data into a table i have created in SQL 2008.
For some reason i keep getting the following error:
"The given value of type String from the data source cannot be converted to type float of the specified target column."
Complete Stack Trace:
System.Data.SqlClient.SqlBulkCopy.ConvertValue(Object value, _SqlMetaData metadata, Boolean isNull, Boolean& isSqlType, Boolean& coercedToDataFeed)
System.Data.SqlClient.SqlBulkCopy.ReadWriteColumnValueAsync(Int32 col)
System.Data.SqlClient.SqlBulkCopy.CopyColumnsAsync(Int32 col, TaskCompletionSource`1 source)
System.Data.SqlClient.SqlBulkCopy.CopyRowsAsync(Int32 rowsSoFar, Int32 totalRows, CancellationToken cts, TaskCompletionSource`1 source)
System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinued(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsync(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestContinuedAsync(BulkCopySimpleResultSet internalResults, CancellationToken cts, TaskCompletionSource`1 source)
System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestAsync(CancellationToken cts, TaskCompletionSource`1 source)
System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalAsync(CancellationToken ctoken)
System.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServerAsync(Int32 columnCount, CancellationToken ctoken)
System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table, DataRowState rowState)
System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table)
RMBEventReportingSystemPOC.Admin.ProcessFile(String strFilename) in \Admin.aspx.cs:line 159
Please find below the code i am using. Please let me know where i have gone wrong :
StatusLabel.Text = "File Process status: File process started!";
try
{
//var fileName = string.Format(strFilename, Directory.GetCurrentDirectory());
SqlConnection con = new SqlConnection(@"**ConnectionString**");
string filepath = Server.MapPath("~/uploads/") + strFilename;
StreamReader sr = new StreamReader(filepath);
string line = sr.ReadLine();
string[] value = line.Split(';');
DataTable dt = new DataTable();
DataRow row;
foreach (string dc in value)
{
if (dc == "Month" || dc == "Year" || dc == "Reply")
dt.Columns.Add(new DataColumn(dc, typeof(int)));
else if (dc == "CostPerHead" || dc == "TotalCost")
dt.Columns.Add(new DataColumn(dc, typeof(float)));
else
dt.Columns.Add(new DataColumn(dc));
}
while (!sr.EndOfStream)
{
value = sr.ReadLine().Split(';');
if (value.Length == dt.Columns.Count)
{
row = dt.NewRow();
//fix up default values
value[1] = value[1] == "" ? "0" : value[1].ToString().Trim();
value[2] = value[2] == "" ? "0" : value[2].ToString().Trim();
value[3] = value[3] == "" ? "0.00" : string.Format("{0:0.00}",value[3].ToString());
value[4] = value[4] == "" ? "0.00" : string.Format("{0:0.00}",value[4].ToString());
value[7] = value[7] == "" ? "0" : value[7].ToString().Trim();
row.ItemArray = value;
dt.Rows.Add(row);
}
}
////fix up default values
for (int i = 0; i < dt.Rows.Count; i++)
{
dt.Rows[i][1] = int.Parse(dt.Rows[i][1].ToString().Trim());
dt.Rows[i][2] = int.Parse(dt.Rows[i][2].ToString().Trim());
dt.Rows[i][3] = Math.Round(float.Parse(dt.Rows[i][3].ToString() + ".00"), 2);
dt.Rows[i][4] = Math.Round(float.Parse(dt.Rows[i][4].ToString() + ".00"), 2);
dt.Rows[i][7] = dt.Rows[i][7].ToString() == "" ? 0 : int.Parse(dt.Rows[i]["Reply"].ToString().Trim());
}
SqlBulkCopy bc = new SqlBulkCopy(con.ConnectionString, SqlBulkCopyOptions.TableLock);
bc.DestinationTableName = "Guestlist";
bc.BatchSize = dt.Rows.Count;
// add column mappings if necessary
con.Open();
bc.WriteToServer(dt);
bc.Close();
con.Close();
StatusLabel.Text = "File Process status: File process completed! " + dt.Rows.Count.ToString() + " records imported.";
StatusLabel.CssClass = "success";
}
catch (Exception exx)
{
StatusLabel.Text = "File Process status: File process failed!: " + exx.Message;
StatusLabel.CssClass = "error";
}
any pointers would be greatly appreciated.
Upvotes: 1
Views: 9542
Reputation: 19437
One or more of your columns are defined as float type in the database.
However, in the CSV file the column value is a string or contains a value that cannot be converted to a float type.
The columns you are converting at
dt.Rows[i][3] = Math.Round(float.Parse(dt.Rows[i][3].ToString() + ".00"), 2);
dt.Rows[i][4] = Math.Round(float.Parse(dt.Rows[i][4].ToString() + ".00"), 2);
may contain a floating point number already. By appending ".00" you are now making it invalid and hence the conversion fails.
Depending on the data, either remove the conversion or make conditional use of it.
Upvotes: 1
Reputation: 1740
SqlBulkCopy.WriteToServer(DataTable)
fails with confusing messages if the column order of the DataTable
differs from the column order of the table definition in your database (when this causes a type or length incompatibility). Apparently the WriteToServer
method does not map column names.
Upvotes: 4
Reputation: 11840
You should use an object array, instead of a string array for the variable called value.
Then call Convert.ToFloat() method on any data you assign to it which is meant to end up in a float column in the database.
When you set the object array to the row.ItemArray, the fields which are float in the database will be floats in your array too, and you should be able to submit to the database ok.
Upvotes: 0