Sql批量复制截断十进制

Kei*_*son 5 c# sql database sql-server 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);
Run Code Online (Sandbox Code Playgroud)

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

Mic*_*Liu 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);  
        }
Run Code Online (Sandbox Code Playgroud)

AdjustSqlDecimalScale反过来打电话SqlDecimal.AdjustScale,传递falsefRound:

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;
}
Run Code Online (Sandbox Code Playgroud)

显然没有办法覆盖这种行为并传递trueAdjustScale,所以如果你想使用SqlBulkCopy,你需要DataTable在调用之前对自己的值进行舍入WriteToServer.

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