SqlBulkCopy - 数据源中给定的字符串类型的值无法转换为指定目标列的货币类型。

81

当我尝试从 DataTable 进行 SqlBulkCopy 时,出现了这个异常。

Error Message: The given value of type String from the data source cannot be converted to type money of the specified target column.
Target Site: System.Object ConvertValue(System.Object, System.Data.SqlClient._SqlMetaData, Boolean, Boolean ByRef, Boolean ByRef)

我明白错误信息的含义,但是我如何获得更多信息,例如此错误发生在哪一行/字段?数据表格由第三方填充,可以包含多达200列和10k行。返回的列取决于发送给第三方的请求。所有数据表格列都是字符串类型。我的数据库列并非全部为varchar,因此,在执行插入之前,我使用以下代码格式化数据表格值(已删除不重要的代码):
//--- create lists to hold the special data type columns
List<DataColumn> IntColumns = new List<DataColumn>();
List<DataColumn> DecimalColumns = new List<DataColumn>();
List<DataColumn> BoolColumns = new List<DataColumn>();
List<DataColumn> DateColumns = new List<DataColumn>();

foreach (DataColumn Column in dtData.Columns)
{
    //--- find the field map that tells the system where to put this piece of data from the 3rd party
    FieldMap ColumnMap = AllFieldMaps.Find(a => a.SourceFieldID.ToLower() == Column.ColumnName.ToLower());

    //--- get the datatype for this field in our system
    Type FieldDataType = Nullable.GetUnderlyingType(DestinationType.Property(ColumnMap.DestinationFieldName).PropertyType);

    //--- find the field data type and add to respective list
    switch (Type.GetTypeCode(FieldDataType))
    {
        case TypeCode.Int16:
        case TypeCode.Int32:
        case TypeCode.Int64: { IntColumns.Add(Column); break; }
        case TypeCode.Boolean: { BoolColumns.Add(Column); break; }
        case TypeCode.Double:
        case TypeCode.Decimal: { DecimalColumns.Add(Column); break; }
        case TypeCode.DateTime: { DateColumns.Add(Column); break; }
    }

    //--- add the mapping for the column on the BulkCopy object
    BulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(Column.ColumnName, ColumnMap.DestinationFieldName));
}

//--- loop through all rows and convert the values to data types that match our database's data type for that field
foreach (DataRow dr in dtData.Rows)
{
    //--- convert int values
    foreach (DataColumn IntCol in IntColumns)
        dr[IntCol] = Helpers.CleanNum(dr[IntCol].ToString());

    //--- convert decimal values
    foreach (DataColumn DecCol in DecimalColumns)
        dr[DecCol] = Helpers.CleanDecimal(dr[DecCol].ToString());

    //--- convert bool values
    foreach (DataColumn BoolCol in BoolColumns)
        dr[BoolCol] = Helpers.ConvertStringToBool(dr[BoolCol].ToString());

    //--- convert date values
    foreach (DataColumn DateCol in DateColumns)
        dr[DateCol] = dr[DateCol].ToString().Replace("T", " ");
}

try
{
    //--- do bulk insert
    BulkCopy.WriteToServer(dtData);
    transaction.Commit();
}
catch (Exception ex)
{
    transaction.Rollback();

    //--- handles error
    //--- this is where I need to find the row & column having an issue
}

这段代码应该为所有目标字段格式化所有值。在出现此错误的情况下,清理数据的函数将删除任何不是0-9或。(小数点)的字符。在数据库中,抛出此错误的字段可以为空。

2级异常产生了以下错误:

Error Message: Failed to convert parameter value from a String to a Decimal.
Target Site: System.Object CoerceValue(System.Object, System.Data.SqlClient.MetaType, Boolean ByRef, Boolean ByRef, Boolean)

第三级异常出现以下错误:

Error Message: Input string was not in a correct format
Target Site: Void StringToNumber(System.String, System.Globalization.NumberStyles, NumberBuffer ByRef, System.Globalization.NumberFormatInfo, Boolean)

有人有什么想法来修复吗?或者有任何想法获取更多信息吗?


2
查看文档,您可以使用NotifyAfter属性,在复制N行时触发事件。它可以帮助您确定默认发生的行所在的批次。 - shahkalpesh
1
你的 CleanDecimal 方法是尝试验证数据还是只是剥离无效字符?你是否尝试使用 Decimal.TryParse() 来检查数据是否实际上处于正确的格式?试一下看看它是否能找出问题值。 - Corey
以下是如何获取有关导致问题的特定列的更多信息的方法:https://medium.com/@shokrano/solving-the-the-given-value-of-type-string-from-the-data-source-cannot-be-converted-to-type-9e34ea3d815d - Shahar Shokrani
11个回答

-3

检查您要写入服务器的数据。可能存在未使用的分隔符。

例如:

045|2272575|0.000|0.000|2013-10-07
045|2272585|0.000|0.000;2013-10-07

你的分隔符是'|',但数据中的分隔符是';'。因此,你会遇到这个错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接