Sql批量复制截断十进制

时间:2014-05-09 13:52:23

标签: c# sql sql-server database datatable

当我使用批量复制从C#DataTable向Sql Server 2005插入十进制值时,值会被截断而不是舍入。

  • DataTable中的数据类型是Decimal。
  • 数据库中的数据类型为十进制(19,3)
  • DataTable中的值为1.0005
  • 数据库中的值插入是1.000(我预计为1.001)

我使用的代码非常简单:

var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, null) { DestinationTableName = tableName};
bulkCopy.WriteToServer(dataTable);

有谁知道如何解决这个问题?

1 个答案:

答案 0 :(得分:10)

根据参考源,SqlBulkCopy总是截断十进制值而不是舍入,这不幸地与BULK INSERT语句的行为不同。

如果源值的比例与目标列的比例不同,则私有ConvertValue方法会调用TdsParser.AdjustSqlDecimalScale

switch(type.NullableType) {
    case TdsEnums.SQLNUMERICN:
    case TdsEnums.SQLDECIMALN:
        // ...

        if (sqlValue.Scale != metadata.scale) {                            
            sqlValue = TdsParser.AdjustSqlDecimalScale(sqlValue, metadata.scale);  
        }

AdjustSqlDecimalScale依次调用SqlDecimal.AdjustScale,将false传递给fRound

static internal SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale) {
    if (d.Scale != newScale) {
        return SqlDecimal.AdjustScale(d, newScale - d.Scale, false /* Don't round, truncate.  MDAC 69229 */);
    }

    return d;
}

显然无法覆盖此行为并将true传递给AdjustScale,因此如果您要使用SqlBulkCopy,则需要对DataTable中的值进行舍入在致电WriteToServer之前你自己。

或者,您可以将数据写入文件并直接执行BULK INSERT,放弃SqlBulkCopy