2011-04-14 71 views
2

我想使用ADO.NET(4.0 SP1)將大量的字符串數據插入到SQLExpress R2的VARCHAR(MAX)字段中。該表具有一個VARCHAR(MAX)列。目前,該字符串的大小是77012287.下面是該查詢:OutOfMemoryException SqlCommand VarChar(Max)

insert into dbo.t_test (c1) values (@c1); 

我目前運行測試應用程序,構建一個新的字符串如下:

private static void ExecuteSqlQuery(int size) { 
     Console.WriteLine("Inserting data. Parameter size: {0}", size); 

     using (SqlConnection cn = new SqlConnection(SQL_CONNECTION_STRING)) { 
      Console.WriteLine("Opening database connection."); 
      cn.Open(); 

      using (SqlCommand cm = cn.CreateCommand()) { 
       cm.CommandType = CommandType.Text; 
       cm.CommandText = SQL_INSERT; 
       cm.CommandTimeout = SQL_COMMAND_TIMEOUT; 
       cm.Parameters.Add(SQL_PARM_DATA, SqlDbType.VarChar, -1).Value = new string('a', size); 

       cm.ExecuteNonQuery(); 
      } 

      Console.WriteLine("Closing database connection."); 
     } 
    } 

我receving SQLException的時試圖用更大的值運行此方法。它從來沒有實際上擊中數據庫(我有異形SQL Express)。 SqlException是ExecuteNonQuery調用中的TimeoutException。如果我運行這個方法幾次,然後用更大的數字運行它,我會在ExecuteNonQuery調用中得到一個System.OutOfMemoryException。它看起來像內部分析器正在嘗試一個字符數組,並拋出一個錯誤。如何從.NET中將大字符串值插入到SQL Express中?謝謝。

+0

出於好奇:多大是「大」? – Mat 2011-04-14 18:08:37

+0

我開始看到一個字符長度爲77012287個字符的錯誤。 – Clay 2011-04-14 18:29:34

+0

爲什麼在SQL Server中存儲77MB字符串?在任何情況下,這些大字符串都會很快導致LOH(大對象堆)中的內存碎片,從而導致出現此類異常。 – 2011-04-14 19:28:50

回答

2

有關如何將大文件流式傳輸到BLOB列的示例,請參閱Download and Upload images from SQL Server via ASP.Net MVC,查看BLOB數據流式上傳部分。您可以從codeproject下載代碼。

它的要點是你需要上傳塊並使用UPDATE set column.WRITE語法,因爲ADO.Net客戶端沒有適當的流語義。

另一種方法是使用FILESTREAM,因爲SqlFileStream類型確實支持流式傳輸,請參閱FILESTREAM MVC: Download and Upload images from SQL Server以獲得完整樣本。但FILESTREAM存儲帶有其怪癖,並不是一個微不足道的決定(特別是如果您的主機不提供它......)。

+0

我最終瀏覽了BLOB與NTFS的白皮書。我決定堅持NTFS並通過數據庫指向它。謝謝你的幫助! – Clay 2011-04-14 18:54:46

2

這聽起來像你的字符串在Large Object Heap結束,而不是壓縮。不幸的是,我不知道強制大型對象堆(LOH)的緊湊或清理的好方法,因此我可以給出的最佳建議是使用較短的字符串。


LOH需要大於80Kb的任何東西。請記住,因爲字符串是不可變的,所以如果隨着時間的推移構建字符串,可能會在創建單個大字符串的過程中將許多不同的字符串插入到LOH中。這些其他字符串將由GC收集,並將物理內存返回給操作系統,但由於LOH未壓縮(經過碎片整理),它們將繼續佔用可用於您的進程的地址空間,該地址空間通常限制在僅2GB。此時您將看到OutOfMemory異常。

+0

144MB的字符串對我來說似乎不是一個大字符串。如果StringBuilder可以很好地構建它,那麼我不明白爲什麼SqlCommand會與它一起掙扎。 – Clay 2011-04-14 18:34:39

+0

@Clay - 我更新了我的答案。閱讀下半場。 – 2011-04-14 19:26:15

+0

我真的很感謝迴應。這對我爲什麼會發生OutOfMemoryException非常有意義。 – Clay 2011-04-14 20:09:45