【问题标题】:SqlBulkCopy Exception Doesn't Contain Column NameSqlBulkCopy 异常不包含列名
【发布时间】:2015-04-03 06:40:56
【问题描述】:

如果传递给 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.

【问题讨论】:

  • 我遇到了类似的问题,尽管挖得相当深也找不到答案,所以我也很想知道答案。
  • 这可能有用csvreader.com/posts/validating_datareader.php。关于这个问题,它指出“使用 SqlBulkCopy 最令人沮丧的是缺乏有用的错误消息”......是的......

标签: .net vb.net exception sqlbulkcopy


【解决方案1】:

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

在您的情况下,我认为您需要将自己的验证添加到 .net 代码中的所有小数列。失败的数字在小数点左侧有 28 位,因此任何精度小于 decimal(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);
    }

【讨论】:

    猜你喜欢
    • 2019-08-26
    • 1970-01-01
    • 1970-01-01
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多