मैं LINQ-to-SQL के साथ मेमोरी रिसाव से कैसे बचूं?


20

मुझे स्मृति उपयोग के आसपास LINQ-To-SQL के साथ कुछ समस्याएं आ रही हैं। मैं इसे कुछ प्रोसेसिंग करने के लिए विंडोज सेवा में उपयोग कर रहा हूं, और मैं डेटा से बड़ी मात्रा में डेटा लूप कर रहा हूं जिसे मैं संदर्भ से वापस खींच रहा हूं। हां - मुझे पता है कि मैं इसे संग्रहीत प्रक्रिया के साथ कर सकता हूं लेकिन ऐसे कारण हैं कि यह आदर्श समाधान से कम क्यों होगा।

वैसे भी, जो मूल रूप से मैं देखता हूं वह स्मृति है जिसे मैं context.SubmitChanges() पर कॉल करने के बाद भी जारी नहीं किया जा रहा है। तो मैं अजीब चीज़ों के सभी प्रकार के काम करने के लिए समाप्त होता हूं जैसे समय पर केवल 100 रिकॉर्ड वापस खींचता हूं, या कई संदर्भ बनाते हैं और उन्हें सभी अलग-अलग कार्य करते हैं। अगर मैं वही DataContext रखता हूं और बाद में इसे अन्य कॉल के लिए उपयोग करता हूं, तो यह अधिक से अधिक स्मृति खाता है। यहां तक ​​कि अगर मैं Clear() को "var tableRows" सरणी पर कॉल करता हूं, तो क्वेरी मुझे वापस लौटाती है, इसे शून्य पर सेट करें, और SYstem.GC.Collect() पर कॉल करें - यह अभी भी स्मृति को जारी नहीं करता है।

अब मैंने कुछ पढ़ा है कि आपको DataContexts का उपयोग कैसे करना चाहिए और जल्दी से उनका निपटान करना चाहिए, लेकिन ऐसा लगता है कि उनके सभी डेटा को डंप करने के लिए संदर्भ को मजबूर करने का एक तरीका होना चाहिए (या इसके सभी ट्रैकिंग डेटा विशेष तालिका) स्मृति की गारंटी के लिए एक निश्चित बिंदु पर मुफ़्त है।

कोई भी जानता है कि स्मृति किस प्रकार की गारंटी देता है कि स्मृति जारी की जाती है?

15

आप वस्तु पर नज़र रखने की जरूरत नहीं है DataContext.ObjectTrackingEnabled सेट झूठी करने के लिए। यदि आपको इसकी आवश्यकता है, तो आप आंतरिक DataContext.ClearCache() पर कॉल करने के लिए प्रतिबिंब का उपयोग कर सकते हैं, हालांकि आपको यह पता होना चाहिए कि इसके आंतरिक होने के बाद, यह ढांचे के भविष्य के संस्करण में गायब हो गया है। और जहां तक ​​मैं कह सकता हूं, ढांचा स्वयं इसका उपयोग नहीं करता है लेकिन ऑब्जेक्ट कैश साफ़ करता है।

+1

ध्यान दें कि जैसा कि अन्य सज्जनों ने कहा, शायद इस स्थिति में कई डेटाकॉन्टेक्स का उपयोग करना बेहतर है। लेकिन, चूंकि सवाल यह था कि एक संदर्भ में स्मृति को रिलीज़ करने की गारंटी कैसे दी जाए, तो ClearCache() विधि उत्तर के करीब है। 24 sep. 082008-09-24 14:43:13

  0

हां, कई डेटाकॉन्टेक्स्ट का उपयोग करें या नहीं, आपके डेटा की मात्रा पर निर्भर करता है, आप सीख सकते हैं कि इससे कैसे निपटें, मैं रोबोनरी एमवीसी रोड श्रृंखला से सीखता हूं ... http://blog.wekeroad.com/category/mvc-storefront 04 sep. 092009-09-04 15:01:53

+3

( \t "ClearCache", \t BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, \t अशक्त, संदर्भ, नल) context.GetType() InvokeMember;: यहाँ कैसे आप ClearCache() कॉल कर सकते हैं है। 08 nov. 102010-11-08 16:42:34

  0

+1, हालांकि मुझे पता चला कि मुझे विधि को कॉल करने के लिए कहने के लिए एक और बाध्यकारी झंडा चाहिए: BindingFlags.InvokeMethod। 11 nov. 102010-11-11 21:38:05

  0

मैंने 'DataContext.ObjectTracking को गलत करने के लिए सक्षम' की कोशिश की, लेकिन जब मैं मेमोरी प्रोफाइलर चलाता हूं 'यह इसे डिस्पोजेड के रूप में इंगित करता है लेकिन जीसीड नहीं किया जा सकता है। 23 jan. 132013-01-23 09:58:32


20

डेटाकॉन्टेक्स्ट उन सभी ऑब्जेक्ट्स को ट्रैक करता है जो इसे कभी भी लाया जाता है। जब तक यह कचरा इकट्ठा नहीं होता है तब तक यह इसे जारी नहीं करेगा। साथ ही, जैसा कि यह IDisposable लागू करता है, आपको Dispose पर कॉल करना होगा या using कथन का उपयोग करना होगा।

यह जाने के लिए सही तरीका है:

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

6

डेविड पॉइंट्स के रूप में, आपको डेटा का उपयोग करके डेटाकॉन्टेक्स्ट का निपटान करना चाहिए।

ऐसा लगता है कि आपकी प्राथमिक चिंता DataContext ऑब्जेक्ट्स का एक गुच्छा बनाने और निपटाने के बारे में है। यह है कि linq2sql कैसे डिज़ाइन किया गया है। डेटाकॉन्टेक्स्ट का संक्षिप्त जीवनकाल होना है। चूंकि आप डीबी से बहुत सारे डेटा खींच रहे हैं, इसलिए यह समझ में आता है कि बहुत मेमोरी उपयोग होगा। भाग में अपने डेटा को संसाधित करके, आप सही रास्ते पर हैं।

डेटाकॉन्टेक्स का एक टन बनाने से डरो मत। वे इस तरह इस्तेमाल करने के लिए डिजाइन किए गए हैं।


3

धन्यवाद दोस्तों - मैं ClearCache विधि की जांच करूंगा।

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

मैं सिर्फ एक समान समस्या में पड़ गए: बस स्पष्टीकरण (भविष्य पाठकों के लिए) के लिए, स्थिति है जिसमें मैं स्मृति usuage हो रही थी कुछ इस तरह था। मेरे मामले में, DataContext.ObjectTrackingEnabled के गुणों को झूठी में स्थापित करने में सहायता मिली। लेकिन यह केवल पंक्तियों के माध्यम से पुनरावृत्ति के मामले में काम करता है:

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() का उपयोग करने के लिए - कोई प्रभाव नहीं