SqlBulkCopy异常不包含列名。

3
如果传入 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
我遇到了一个类似的问题,尽管我已经深入挖掘,但仍然找不到答案,所以我非常想知道答案。 - Elliveny
2
这可能会有用 http://www.csvreader.com/posts/validating_datareader.php。关于这个问题,它指出:“使用SqlBulkCopy最令人沮丧的事情是缺乏有用的错误消息”...是的... - Elliveny
1个回答

3
我认为简短的答案是否定的,没有办法让SqlBulkCopy告诉您哪一列出了问题。在您的情况下,我认为您需要在.net代码中添加自己的验证到所有十进制列。失败的数字在小数点左侧有28位数字,因此任何SQL列精度小于decimal(28,0)都会导致插入失败。请查看关于验证.net十进制数存储在SQL中的以下问题: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);
    }

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