2014-04-22 16 views
7

Phần mềm được sử dụng: Windows 7 64 bit Ultimate, .Net 4, SQL Server 2008 R2 .Lạ "Nhà cung cấp OLE DB 'STREAM' cho máy chủ được liên kết '(null)' trả lại dữ liệu không hợp lệ cho cột '[! BulkInsert] .Value' lỗi

chọn @@ phiên bản lợi nhuận:

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) 

Để tái sản xuất, và giả sử bạn có một máy chủ sql địa phương 2008 R2 Ví dụ, dán đoạn mã sau vào LINQPad và chạy nó như là một chương trình

. Nó thổi lên với:

Nhà cung cấp OLE DB 'STREAM' cho máy chủ được liên kết '(null)' trả lại dữ liệu không hợp lệ cho cột '[! 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(); 
    } 
} 

Tôi có thể sẽ tạo một trường hợp với Microsoft, nhưng tôi tò mò muốn xem có ai khác nhìn thấy điều này trước đây không và nếu có cách giải quyết nào khác. Dường như không phải tất cả các số không đều được tạo ra bằng nhau.

Chỉ cần cập nhật:

Tôi đã mở một trường hợp với Microsoft. Phải mất gần 2 tháng để đưa ra một số cờ dbcc không có giấy tờ không rõ ràng để tắt tính hợp lệ của các giá trị được bơm qua bản sao số lượng lớn vào cột biến thể. Trường hợp bị trả về giữa các nhóm khác nhau (sự hỗ trợ được cung cấp bởi các nhà thầu tư nhân Ấn Độ) và họ chưa bao giờ gặp vấn đề gốc mà tôi cho rằng nó liên quan đến giá trị được tạo ra bởi các dòng sau và cách xử lý bởi mã sao chép :

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

Vì vậy, để kết luận, thật đáng thất vọng và tôi đã từ bỏ vì đó là một sự cố hiếm xảy ra.

Trả lời

3

Giải pháp được chỉ ra bởi Microsoft và cái mà tôi đã sử dụng, là sử dụng lá cờ không có giấy tờ này: DBCC TRACEON (7307, -1). Bạn có thể kích hoạt nó ở cấp kết nối hoặc ở cấp độ máy chủ.

14

Nếu kiểu dữ liệu của bạn cho cột 'giá trị' là nổi, vấn đề có khả năng của bạn là bạn gửi một máy chủ double.NaN đến sql, mà nó không thích.

Xin lưu ý rằng một cuộc gọi như double.TryParse ("NaN", ra dv) vui vẻ sẽ trở thành sự thật và thiết lập các dv để double.NaN

Hope this helps, K.

+0

Loại cột là sql_variant. – costa

+0

không biết nếu cột sqlvariant có thể lưu trữ NaN nhưng bạn có thể thay đổi loại cột thành varchar để xem lỗi có còn tồn tại hay không. –

+0

Tôi không muốn thay đổi nó thành varchar vì nó phải là sql_variant. – costa

0

Lỗi này được ném nếu double.NaN nằm trong bảng, do đó, hãy chuyển đổi thành null thay thế.

Tôi đã sử dụng phương pháp tiện ích mở rộng này để loại bỏ vấn đề này.

Để sử dụng, thêm .MyToNullIfNan() cho bất kỳ double hoặc double?, và nó sẽ tạo ra một double? đó là null nếu 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; 
    } 
} 
+1

Gốc của vấn đề ở đây là 8m và -8m khi được đặt trong một danh sách và tóm tắt bằng cách sử dụng LINQ, tạo ra một khoản tiền không thể được lưu thông qua SqlBulkCopy. Microsoft đã không cung cấp bản sửa lỗi thích hợp. Xin lưu ý rằng tôi đã phải sử dụng loại thập phân và không phải gấp đôi. – costa

+0

Cảm ơn. Trong trường hợp của tôi, vấn đề là 'double.NaN' không thể được lưu vào cơ sở dữ liệu. Giải pháp là chuyển đổi chúng thành null. – Contango

Các vấn đề liên quan