C# 中的 SqlBulkCopy 类正在更改数值

Posted

技术标签:

【中文标题】C# 中的 SqlBulkCopy 类正在更改数值【英文标题】:SqlBulkCopy class in C# is changing a numeric value 【发布时间】:2020-10-31 01:39:28 【问题描述】:

我正在使用SqlBulkCopy.WriteToServer-方法将批量数据插入数据库表。当我将数据表作为方法WriteToServer 的参数传递时,一些数值(numeric(17,6)) 在插入数据库表时被.000001 减去。但并非所有值都在发生变化,它是随机发生的,无法识别模式。例如- 10068.121 正在更改为 10068.120999

现在,当我将数据读取器作为方法 WriteToServer 的参数传递时,它工作正常,数值保持不变。

知道为什么它发生在数据表而不是数据读取器上吗? 我的应用程序是 C# 控制台应用程序。

这是我的代码……如果我将数据表 (_dt) 传递给 _sqlBulkCopy.WriteToServer 方法,那么我就有问题了。但是当我将数据表 (_dt) 转换为 DataTableReader (_Reader) 时,它工作正常。

DataTable _dt = new DataTable();
_odbCDA.Fill(_dt);
DataTableReader _Reader = new DataTableReader(_dt);

using (SqlBulkCopy _sqlBulkCopy = new SqlBulkCopy(_sqlConnectionString)) 

     _sqlBulkCopy.BulkCopyTimeout = 3600;
     _sqlBulkCopy.DestinationTableName = _tableName;
     _sqlBulkCopy.WriteToServer(_Reader); //This works
     //_sqlBulkCopy.WriteToServer(dt); //This is having the issue
     _sqlBulkCopy.Close();

【问题讨论】:

【参考方案1】:

如果没有示例复制很难确定,但是如果我不得不猜测您何时使用 DataReader 您正在两个具有相同数字类型定义/精度的表之间复制数据,但是当使用DataTable 该列没有匹配精度。这大概是因为 DataReader 没有将事物映射到 .NET 类型,但 DataTable 是。

认为(但尚未测试).NET 类型映射大概是这样(至少在 SQL Server 中):

C# float -> SQL real C# double -> SQL float C# decimal -> SQL moneynumeric

SQL 允许您以 C# 所不具备的方式指定精度,因此如果您使用 C# 内置类型,则很有可能您正在执行与 numeric(17,6) 之间的转换,这可能会丢失精度。

如果我的猜测是正确的,DataTable 中受影响的DataColumn 上的DataType 将类似于System.DoubleSystem.SingleSystem.Decimal

【讨论】:

谢谢凯文....对不起,我没有提到...我将相同的数据表转换为数据读取器,所以精度,规模一切都是一样的。在我的调试中,我发现数据表中显示了正确的值(它作为 SqlBulkCopy.WriteToServer 方法中的参数传递)......所以,问题仅出现在 SqlBulkCopy.WriteToServer 方法中,该方法会更改值并插入在数据库表中。 您能否添加您的转换代码以及问题涉及的各种类型?我不太了解您如何在 C# 中表达 numeric(17,6),代码可能会有所帮助。 Kevin,我在问题描述中添加了代码。我的意思是 Numeric(17,6) 是对应的数据库字段类型。 @DebasisD 查看reference source,似乎 SqlBulkCopy 在某些情况下会以不同的方式对待读取器和表。我的直觉仍然是DataTable、remarks 建议这样的转换。 _dt.Columns[<index of troublesome column>].DataType_Reader.GetFieldType(<index of troublesome column>) 的值是多少? Kevin,我检查了字段类型,都是 Double。列名是“共享”。奇怪的情况是,_dt.column 下的所有值都没有发生这个问题,在 200 万条记录中,我发现只有 312,Rest 没有改变。 dt.Columns[].DataType = "Double" and _Reader.GetFieldType() = "Double"。

以上是关于C# 中的 SqlBulkCopy 类正在更改数值的主要内容,如果未能解决你的问题,请参考以下文章

SqlBulkCopy 截断 VARCHAR(MAX) 列中的字符串

C# 使用SqlBulkCopy类批量复制大数据

C#使用SQLBulkCopy或等效库高效批量删除50000条记录

使用 SqlBulkCopy 连接到 SQLite 数据库

使用asp.net 2.0中的SqlBulkCopy类批量复制数据

使用 SQLBulkCopy 插入/更新数据库