SqlBulkCopy异常不包含列名

时间:2015-02-03 22:01:24

标签: .net vb.net exception sqlbulkcopy

如果传递给SqlBulkCopy.WriteToServer()的DataTable包含无法转换的值,则会出现InvalidOperationException,显示无法转换的值。列名不显示在我能说的异常中的任何位置。当发生这种情况时,我正在尝试记录列名和值。有没有办法检索这些信息?

System.InvalidOperationException: The given value of type SqlDecimal from the 
    data source cannot be converted to type decimal of the specified target column. 
    ---> System.InvalidOperationException: The given value of type SqlDecimal from 
    the data source cannot be converted to type decimal of the specified target column. 
    ---> System.ArgumentException: Parameter value '9999999999999999999999999999.00' 
    is out of range.

1 个答案:

答案 0 :(得分:2)

我认为简短的答案是否定的,没有办法让SqlBulkCopy告诉你哪个列导致了问题。

在您的情况下,我认为您需要将自己的验证添加到.net代码中的所有十进制列。失败的数字在小数点左侧有28位数字,因此任何精度小于十进制(28,0)的SQL列都将使此插入失败。看看有关验证SQL的.net小数的这个问题:

Validating decimal in C# for storage in SQL Server

从更一般的意义上讲,如果.net DataTable列排序与SQL表不匹配,则会出现类似错误。在具有以下顺序的列的表中,VarcharColumn,IntColumn,DecimalColumn,即使您已命名列,下表也将无法插入:

        DataTable tbl = new DataTable();
        tbl.Columns.Add("IntColumn", Type.GetType("System.Int32"));            
        tbl.Columns.Add("VarcharColumn", Type.GetType("System.String"));                        
        tbl.Columns.Add("DecimalColumn", Type.GetType("System.Decimal"));

您需要重新订购上面的C#列或提供列映射:

        SqlBulkCopy blkCpy = new SqlBulkCopy(conn);            
        blkCpy.ColumnMappings.Add("VarcharColumn", "VarcharColumn");
        blkCpy.ColumnMappings.Add("IntColumn", "IntColumn");
        blkCpy.ColumnMappings.Add("DecimalColumn", "DecimalColumn");

另一个技巧是,如果您正在调试一个知道某个特定行无法插入的批处理,则可以使用SQLBulkCopy的SQLRowsCopied事件来标识导致问题的行。例如:

        SqlBulkCopy blkCpy = new SqlBulkCopy(conn);
        blkCpy.SqlRowsCopied += blkCpy_SqlRowsCopied;
        blkCpy.NotifyAfter = 1;

然后在事件处理程序中:

    static void blkCpy_SqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
    {
        Console.WriteLine("Copied {0} rows", e.RowsCopied);
    }