奇怪的"OLE DB提供程序'STREAM'用于链接服务器'(null)'返回列'[!BulkInsert] .Value'错误的无效数据

cos*_*sta 12 sqlbulkcopy sql-server-2008-r2 c#-4.0

使用的软件:Windows 7 64位Ultimate,.Net 4,SQL Server 2008 R2.

select @@ version返回:

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

要重现,并假设您有本地sql server 2008 R2实例,请将以下代码粘贴到linqpad中并将其作为程序运行.

它爆炸了:

链接服务器'(null)'的OLE DB提供程序'STREAM'返回列'[!BulkInsert] .Value'的无效数据.

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

我可能会与微软创建一个案例,但我很想知道其他人之前是否看过这个案例,以及是否有任何变通办法.似乎并非所有的零都是平等的.

只是一个更新:

我向微软公开了一个案例.他们花了将近2个月的时间才想出一些模糊的无证件dbcc标志,该标志关闭了通过批量副本泵入变量列的值的验证.案件在不同的团队之间反弹(支持由印度私人承包商提供),他们从来没有遇到根本问题,我认为这与以下几行产生的价值有关,以及如何通过批量复制代码处理:

  IList<decimal> list = new List<decimal>() {-8m, 8m};
  decimal result = list.Sum(x => x);
Run Code Online (Sandbox Code Playgroud)

因此,总而言之,这是令人失望的,我放弃了,因为这是罕见的事情.

Kem*_*gan 17

如果列'value'的数据类型是float,那么你可能遇到的问题是你发送了一个double.NaN到sql server,它不喜欢它.

请注意,像double.TryParse("NaN",out dv)之类的调用将很高兴返回true并将dv设置为double.NaN

希望这会有所帮助,K.


Con*_*ngo 6

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


cos*_*sta 5

Microsoft 指出的、我最终使用的解决方案是使用这个未记录的标志:DBCC TRACEON (7307, -1)。您可以在连接级别或服务器级别启用它。