2008-09-23 106 views
20

我一直在使用LINQ-to-SQL存在一些問題。我在Windows服務中使用它來做一些處理,並且我正在循環大量從上下文中撤回的數據。是的 - 我知道我可以用存儲過程來做到這一點,但有理由說這是一個不太理想的解決方案。如何避免使用LINQ到SQL的內存泄漏?

無論如何,我基本上看到的是內存不被釋放,即使我打電話context.SubmitChanges()後。所以我最終不得不做各種奇怪的事情,比如只在時間拉回100條記錄,或者創建幾個上下文,讓他們都做單獨的任務。如果我保留相同的DataContext並稍後將其用於其他呼叫,則它只會佔用越來越多的內存。即使我在查詢返回給我的「var tableRows」數組上調用Clear(),將其設置爲null,並調用SYstem.GC.Collect() - 它仍然不釋放內存。

現在我已閱讀了一些關於如何快速使用DataContexts並快速處理它們的方法,但似乎他們應該是強制上下文將所有數據(或其所有跟蹤數據特定的表格)以確保內存是免費的。

任何人都知道哪些步驟可以保證內存被釋放?

回答

15

如果您不需要對象跟蹤設置DataContext.ObjectTrackingEnabled。如果你確實需要它,你可以使用反射來調用內部的DataContext.ClearCache(),雖然你必須知道,因爲它的內部,它將在未來的框架版本中消失。據我所知,框架本身並沒有使用它,但它清除對象緩存確實

+1

注意正如其他先生們所說,在這種情況下使用多個DataContexts可能會更好。但是,由於問題是如何保證在一個上下文中釋放內存,ClearCache()方法更接近答案。 – 2008-09-24 14:43:13

20

DataContext跟蹤它曾經獲取的所有對象。在收集垃圾之前它不會釋放它。此外,由於它實施IDisposable,您必須致電Dispose或使用using聲明。

這是正確的方式去:

using(DataContext myDC = new DataContext) 
{ 
    // Do stuff 
} //DataContext is disposed 
6

正如David指出的那樣,您應該使用using塊來處理DataContext。

看來您的主要關注點是創建和配置一堆DataContext對象。這是linq2sql的設計。 DataContext的使用壽命很短。由於您從數據庫中提取大量數據,因此會有很多內存使用情況。通過以塊處理數據,您正處於正確的軌道上。

不要害怕創建大量的DataContexts。它們被設計成以這種方式使用。

3

謝謝你們 - 我將檢查ClearCache方法。只是爲了澄清(對於未來的讀者),在我得到的內存usuage的情況是這樣的:

using(DataContext context = new DataContext()) 
{ 
    while(true) 
    { 
     int skipAmount = 0; 
     var rows = context.tables.Select(x => x.Dept == "Dept").Skip(skipAmount).Take(100); 

     //break out of loop when out of rows 

     foreach(table t in rows) 
     { 
     //make changes to t 
     } 

     context.SubmitChanges(); 
     skipAmount += rows.Count(); 

     rows.Clear(); 
     rows = null; 

     //at this point, even though the rows have been cleared and changes have been 
     //submitted, the context is still holding onto a reference somewhere to the 
     //removed rows. So unless you create a new context, memory usuage keeps on growing 
    } 
} 
0

我只是碰到了類似的問題。在我的情況下,幫助建立屬性DataContext.ObjectTrackingEnabled爲false。 但它只如下工作在通過行迭代的情況:

using (var db = new DataContext()) 
{ 
    db.ObjectTrackingEnabled = false; 
    var documents = from d in db.GetTable<T>() 
        select d; 
    foreach (var doc in documents) 
    { 
     ... 
    } 
} 

如果,例如,在查詢中使用的方法ToArray的()或ToList() - 不影響