使用的软件:Windows 7 64位旗舰版,.Net 4,SQL Server 2008 R2。
选择@@版本返回:
Microsoft SQL Server 2008 R2 (RTM) - 10.50.1617.0 (X64) Apr 22 2011 19:23:43 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (Hypervisor)
要重现,并假设您有本地sql server 2008 R2实例,请将以下代码粘贴到linqpad中并将其作为程序运行。
它爆炸了:
OLE DB提供商&#39; STREAM&#39;对于链接服务器&#39;(null)&#39;返回列&#39; [!BulkInsert] .Value&#39;的无效数据。
void Main()
{
SqlConnection cn = new SqlConnection("data source=localhost;Integrated Security=SSPI;initial catalog=tempdb;Connect Timeout=180;");
cn.Open();
IList<decimal> list = new List<decimal>() {-8m, 8m};
decimal result = list.Sum(x => x);
Console.WriteLine(result == 0);
string tableName = "#test";
CreateTemporaryTable(cn, tableName,
String.Format(@"
create table {0} (
Value sql_variant
);
", tableName));
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(cn);
sqlBulkCopy.DestinationTableName = tableName;
DataTable dt = new DataTable();
dt.Columns.Add("Value", typeof(object));
dt.Rows.Add(result);
sqlBulkCopy.WriteToServer(dt);
sqlBulkCopy.Close();
cn.Close();
}
// Define other methods and classes here
public static void CreateTemporaryTable(SqlConnection cn, string destinationTableName, string createTableStatement)
{
string objectIdValue = (destinationTableName.StartsWith("#") ? "tempdb.." : "") + destinationTableName;
string sql = String.Format(@"
if (object_id (N'{0}', N'U') is not null)
begin
drop table {1};
end;
{2}
", objectIdValue, destinationTableName, createTableStatement);
// Console.WriteLine(sql);
SqlCommand cmd = new SqlCommand(sql, cn);
try
{
cmd.ExecuteNonQuery();
}
finally
{
cmd.Dispose();
}
}
我可能会在微软创建一个案例,但我很想知道其他人之前是否看过这个案例,以及是否有任何变通办法。似乎并非所有的零都是平等的。
只是更新:
我向微软公开了一个案例。他们花了将近2个月的时间才想出一些模糊的无证件dbcc标志,该标志关闭了通过批量副本泵入变量列的值的验证。案件在不同的团队之间反弹(支持由印度私人承包商提供),他们从来没有遇到根本问题,我认为这与以下几行产生的价值有关,以及如何通过批量复制代码处理:
IList<decimal> list = new List<decimal>() {-8m, 8m};
decimal result = list.Sum(x => x);
所以,总而言之,这是令人失望的,我放弃了,因为这种情况很少发生。
答案 0 :(得分:16)
如果列'value'的数据类型是float,则可能的问题是你将double.NaN发送到它不喜欢的sql server。
请注意,像double.TryParse(“NaN”,out dv)之类的调用将很高兴返回true并将dv设置为double.NaN
希望这有帮助, ķ。
答案 1 :(得分:3)
Microsoft指出的解决方案是我最终使用的解决方案是使用这个未记录的标志:DBCC TRACEON(7307,-1)。您可以在连接级别或服务器级别启用它。
答案 2 :(得分:2)
如果表中有double.NaN
,则会抛出此错误,因此请转换为null
。
我使用这种扩展方法来摆脱这个问题。
要使用,请将.MyToNullIfNan()
附加到任何double
或double?
,如果double?
,则会生成null
NaN
。
public static class MyToNullIfNanExtension
{
public static double? MyToNullIfNan(this double? result)
{
if (result.HasValue)
{
if (double.IsNaN(result.Value) || double.IsInfinity(result.Value))
{
return null;
}
}
return result;
}
public static double? MyToNullIfNan(this double result)
{
if (double.IsNaN(result) || double.IsInfinity(result))
{
return null;
}
return result;
}
}
答案 3 :(得分:0)
当列映射中的字段中的数据类型之间存在分歧时,会发生此错误。
例如,当字符串列映射到uniqueidentifier字段时,即使在验证没有任何空白/空值可能导致guid出现问题之后,也会发生此错误。
bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("GuidColumn", "SqlGuidColumn"));
这两个都需要在输入时完全匹配,以免你从OLEDB得到奇怪的错误!
批量复制非常适用于将大型数据集写入表中的高I / O操作...但是,它并不能很好地指出特定行在整个集合中失败的原因。忽略行级操作使得它的执行速度比逐行快。