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 money
或 numeric
SQL 允许您以 C# 所不具备的方式指定精度,因此如果您使用 C# 内置类型,则很有可能您正在执行与 numeric(17,6)
之间的转换,这可能会丢失精度。
如果我的猜测是正确的,DataTable
中受影响的DataColumn
上的DataType
将类似于System.Double
、System.Single
或System.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或等效库高效批量删除50000条记录