Weird "OLE DB provider 'STREAM' for linked server '(null)' returned invalid data for column '[!BulkInsert].Value' error

白昼怎懂夜的黑 提交于 2021-02-07 11:24:59

问题


Software used: Windows 7 64 bit Ultimate, .Net 4, SQL Server 2008 R2.

select @@version returns:

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) 

To reproduce, and assuming you have a local sql server 2008 R2 instance, paste the following code in linqpad and run it as a Program.

It blows up with:

OLE DB provider 'STREAM' for linked server '(null)' returned invalid data for column '[!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();
  }
}

I will probably create a case with Microsoft, but I was curious to see if someone else saw this before, and if there are any workarounds. It seems that not all the zeros are created equal.

Just an update:

I opened a case with Microsoft. It took them almost 2 months to come up with some obscure undocumented dbcc flag that turns off the validation of the values that get pumped via the bulk copy into the variant column. The case was bounced between the different teams (the support was provided by Indian private contractors) and they never got to the root problem which I think it is related to the value produced by the following lines and how it is handled by the bulk copy code :

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

So, to conclude, it was disappointing and I gave up because it is a rare occurrence.


回答1:


If your data type for the column 'value' is float, your likely problem is that you send a double.NaN to sql server, which it does not like.

Please note that a call like double.TryParse( "NaN", out dv) will happily return true and set the dv to double.NaN

Hope this helps, K.




回答2:


This error is thrown if double.NaN is in the table, so convert to null instead.

I used this extension method to get rid of this issue.

To use, append .MyToNullIfNan() to any double or double?, and it will produce a double? which is null if 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:


The solution indicated by Microsoft and which I ended up using, is to use this undocumented flag: DBCC TRACEON (7307, -1). You can enable it at the connection level or at the server level.




回答4:


This error tends to happen when there's a disagreement between data types in the fields in the column mapping.

For instance, this error can happen when a string column is mapped to a uniqueidentifier field, even after verifying there weren't any blank/null values that could cause trouble for a guid.

bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("GuidColumn", "SqlGuidColumn"));

Both of these require an exact match on typing, lest you get strange errors from OLEDB!

Bulk copy is fantastic for high I/O operations where you're writing large datasets into a table... However, it is not great at indicating why a specific row fails in the entire set. It's the ignoring of row-level operations that makes this perform vastly faster than row-by-row.



来源:https://stackoverflow.com/questions/23229862/weird-ole-db-provider-stream-for-linked-server-null-returned-invalid-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!