2011-02-28 45 views
0

底層表在SQL Server 2008 R2中有一個int,guid和Filestream列。文件流顯示爲byte []。我觀察到的是內存消耗不斷增加。我該怎麼辦?ADO.NET實體拋出OutOfMemoryException。如何防止這種情況

MyEntities bh = new MyEntities(); 
foreach (var s in bh.TaskGraphs) 
{ 
    try 
    { 
     using (var x = new MemoryStream(s.TaskGraph1)) 
     { 
      //var t = TaskGraph.Load(x); 
      //Validate(t); 
     } 
    } 
    catch (Exception e) 
    {     
    } 
} 

這裏的內存使用模式

enter image description here

我現在發現,這樣做bh.TaskGraphs.Select(P =>新{p.TaskGraph1,p.StreamId}使異常消失,這是由於與此表中的子表?

順便說一句,每個BLOB是〜3MB

+0

即使我註釋掉函數中使用錯誤調用仍然發生 – 2011-02-28 17:59:38

+0

你能後的錯誤之一*全*堆棧跟蹤? – 2011-02-28 18:03:09

+0

你在使用實體框架嗎?請告訴我們一些涉及的數據量。 – 2011-02-28 18:05:52

回答

1

實體框架在實體容器中加載實體,容器有一個實體集合,其中包含從數據庫中提取的實體的本地副本。每個實體都有一個對應實體集的引用,並且整個實體集將保留在內存中,並且實體集將隨着您從數據庫中加載而持續增長。

您必須將表格分成兩部分,使用一對一關係與包含主鍵和其他屬性的表以及另一個僅包含主鍵和blob的表。

接下來在迭代過程中的for循環中,您應該通過新的上下文加載blob實體並處理您的字節數組並在for循環結束時銷燬您的上下文。或者,您也可以從實體容器中分離出一個對象,使其可以免費進行垃圾收集。

在你現有的代碼中,你可以分離你的實體,它將釋放它所持有的內存。

MyEntities bh = new MyEntities(); 
foreach (var s in bh.TaskGraphs) 
{ 
    try 
    { 
        using (var x = new MemoryStream(s.TaskGraph1)) 
        { 
            //var t = TaskGraph.Load(x); 
            //Validate(t); 
      bn.Detach(t); 
        } 
    } 
    catch (Exception e) 
    {                 
    } 
} 
+0

對不起iPhone無法格式化代碼 – 2011-02-28 19:59:27

+0

似乎工作。謝謝。還嘗試了相當於bh.TaskGraphs.MergeOption = System.Data.Objects.MergeOption.NoTracking; – 2011-02-28 20:16:37

0

很難沒有更多的信息說,但我suppo本身,以下是這個問題的至少一部分:

  1. TaskGraphs具有行的很多或Filestream列包含大量的日期
  2. TaskGraph.Load和/或Validate保持該數據的引用,所以它不會被垃圾收集。
  3. 對象上下文MyEntitiesFilestream列保留在內存中一段時間​​,然後再次釋放它。
0

我認爲TaskGraph表有很多記錄,所以當你調用bh.TaskGraphs時,它會將整個表加載到內存中,並且其中的二進制數據比可用內存大。 您應該嘗試僅使用存儲過程以另一種方式加載您想要從數據庫中獲取的記錄。 但首先嚐試這個:

using(MyEntities bh = new MyEntities()) 
{ 
    your code..... 
} 
相關問題