2010-06-16 7 views
6

मेरे पास एक वेबसाइट पर प्रदर्शित संस्थाओं के लिए एक काफी जटिल linq है। यह पेजिंग का उपयोग करता है इसलिए मैं प्रदर्शन के लिए एक समय में 50 से अधिक रिकॉर्ड नहीं खींचता।लिंक से इकाइयों के साथ बड़े परिणाम सेट से कैसे निपटें?

लेकिन मैं उपयोगकर्ता को एक्सेल या कुछ अन्य फ़ाइल प्रारूप में पूर्ण परिणाम निर्यात करने का विकल्प भी देना चाहता हूं।

मेरी चिंता यह है कि ऐसा करने के लिए एक बार मेमोरी में लोड होने वाले रिकॉर्डों का एक बड़ा # संभावित रूप से लोड हो सकता है।

क्या एक समय में एक linq परिणाम सेट 1 रिकॉर्ड को संसाधित करने का कोई तरीका है जैसे आप एक डैटरेडर कर सकते हैं, इसलिए एक समय में केवल 1 रिकॉर्ड स्मृति में रखा जा रहा है?

मैंने सुझावों को देखा है कि यदि आप linq क्वेरी w/एक foreach loop पर गिनती करते हैं कि रिकॉर्ड सभी को एक बार में स्मृति में नहीं पढ़ा जाएगा और सर्वर को ओवरवेल नहीं करेगा।

क्या किसी के पास ऐसा कुछ करने का लिंक है जिसे मैं सत्यापित करने के लिए पढ़ सकता हूं?

मैं किसी भी मदद की सराहना करता हूं।

धन्यवाद

+2

परिणाम डिफ़ॉल्ट रूप से इन-मेमोरी संग्रह नहीं होना चाहिए - क्या आप कुछ ऐसा कर रहे हैं (ToArray, ToList, जो भी हो) इसे सभी को स्मृति में लाया जा सकता है? यदि नहीं, तो परिणामों पर केवल पुनरावृत्ति करें (foreach, चुनें, जो भी हो) और आपको ठीक होना चाहिए। –

+1

वर्तमान में मेरी क्वेरी विधि ToList() को कॉल करती है और सूची लौटाती है लेकिन मैं इसके बजाय QueryObject को वापस करने के लिए आसानी से बदल सकता हूं। क्या आप निश्चित हैं कि यदि मैं IQueryable पर फ़ोरैच लूप करता हूं तो यह डेटा स्ट्रीम करेगा? – user169867

+0

तो आपकी 'ToList() 'मूल रूप से' सूची सूची = नई सूची () जैसी कुछ करेगी; foreach (क्वेरी में ऑब्जेक्ट ऑब्जेक्ट) {list.Add (ऑब्जेक्ट); } '। 'Foreach'' query.MoveNext() 'कॉल करेगा। इसलिए आप सूची में सब कुछ लोड कर रहे हैं और अपनी मेमोरी उपयोग में वृद्धि कर रहे हैं। (मैंने GetEnumerator() टुकड़ा इत्यादि छोड़ दिया है, इसलिए यह सटीक नहीं है) –

उत्तर

5

set the ObjectContext to MergeOption.NoTracking (क्योंकि यह एक केवल पढ़ने के लिए आपरेशन है)। यदि आप संदर्भ से अन्य डेटा, Detach the object सहेजने के लिए उसी ObjectContext का उपयोग कर रहे हैं।

कैसे अलग करने

foreach(IQueryable) 
{ 
    //do something 
    objectContext.Detach(object); 
} 

संपादित: आप NoTracking विकल्प का उपयोग कर रहे हैं, तो वहाँ अलग करने

EDIT2 कोई जरूरत नहीं है: मैं इस परिदृश्य के बारे में Matt Warren को पत्र लिखा। और यहाँ प्रासंगिक निजी पत्राचार पोस्टिंग कर रहा हूँ, उसकी स्वीकृति

एसक्यूएल सर्वर से परिणाम नहीं भी सभी सर्वर द्वारा अभी तक का उत्पादन किया जा सकता है के साथ। क्वेरी सर्वर पर शुरू हो गई है और परिणाम के पहले बैच को क्लाइंट में स्थानांतरित कर दिया गया है, लेकिन अधिक उत्पादित नहीं किए जाते हैं (या वे सर्वर पर कैश किए जाते हैं) जब तक क्लाइंट उन्हें पढ़ने जारी रखने के अनुरोध नहीं होते हैं। इसे 'फ़ायरहोज कर्सर' मोड कहा जाता है, या कभी-कभी स्ट्रीमिंग के रूप में को संदर्भित किया जाता है। सर्वर उन्हें भेज रहा है के रूप में तेजी से के रूप में यह कर सकते हैं, और ग्राहक उन्हें जितनी जल्दी के रूप में यह (अपने कोड), लेकिन वहाँ है कि नीचे एक डेटा ट्रांसफर प्रोटोकॉल है भेजना जारी रखने ग्राहक से पावती की आवश्यकता कर सकते हैं पढ़ रही है अधिक डेटा IEnumerable से

IQueryable के बाद से इनहेरिट करती है, मेरा मानना ​​है कि अंतर्निहित सर्वर के लिए भेजा क्वेरी ही होगा। हालांकि, जब हम IEnumerable.ToList() करते हैं, तो डेटा रीडर, जो अंतर्निहित कनेक्शन द्वारा उपयोग किया जाता है, ऑब्जेक्ट को पॉप्युलेट करना शुरू कर देगा, ऑब्जेक्ट्स ऐप डोमेन में लोड हो जाएंगे और इन ऑब्जेक्ट्स को स्मृति से बाहर चलाया जा सकता है, इन ऑब्जेक्ट्स को अभी तक डिस्पोजेक्ट नहीं किया जा सकता है।

जब आप foreach और IEunmerable का उपयोग कर रहे हैं तो डेटा रीडर एक समय में SQL परिणाम सेट को पढ़ता है, ऑब्जेक्ट्स बनाए जाते हैं और फिर डिस्प्ले किए जाते हैं। अंतर्निहित कनेक्शन भाग में डेटा प्राप्त कर सकता है और जब तक सभी भाग पढ़े जाते हैं तब तक SQL सर्वर को प्रतिक्रिया नहीं भेज सकती है।

जब आपकी क्वेरी चल रहा है, आप वास्तव में अपने एसक्यूएल सर्वर "गतिविधि मॉनिटर" खोलने के लिए और क्वेरी को देख सकते हैं, के रूप में कार्य राज्य: इसलिए आप 'memory` अपवाद से बाहर

Edit3 में नहीं चलेंगे निलंबित और प्रतीक्षा प्रकार Async_network_IO - जो वास्तव में बताता है कि परिणाम SQL सर्वर नेटवर्क बफर में है। आप इसके बारे में अधिक पढ़ सकते हैं here और here

+0

हां, नोट्रैकिंग सेटिंग को भी मदद करनी चाहिए। क्या आपको पता है कि पूरे संदर्भ पर इसे सेट करने का कोई तरीका है या नहीं? मैं इसे सामग्री के अंदर ऑब्जेक्टसेट पर सेट कर रहा हूं। – user169867

+0

क्या आप 'objectContext.MergeOption = MergeOption.NoTracking' की तलाश में हैं? http://msdn.microsoft.com/en-us/library/bb738896.aspx – ram

+0

मुझे नहीं लगता कि ऑब्जेक्ट कॉन्टेक्स्ट में एक मर्जऑपशन प्रॉपर्टी है। क्या आप इसके बजाय ObjectQuery के बारे में सोच रहे हैं? – user169867

1

LINQ क्वेरी के वापसी मूल्य को देखें। यह IEnumerable<> होना चाहिए, जो एक समय में केवल एक वस्तु को लोड करता है। यदि आप .ToList() जैसे कुछ का उपयोग करते हैं, तो वे सभी स्मृति में लोड हो जाएंगे। बस सुनिश्चित करें कि आपका कोड एक सूची बनाए रखता है या एक समय में एक से अधिक उदाहरणों का उपयोग नहीं करता है और आप ठीक होंगे।

संपादित करें: लोगों foreach के बारे में क्या कहा है के लिए पर जोड़ने के लिए ... आप की तरह कुछ करते हैं:

var query = from o in Objects 
      where o.Name = "abc" 
      select o; 

foreach (Object o in query) 
{ 
    // Do something with o 
} 

क्वेरी भाग आस्थगित निष्पादन (see examples) का उपयोग करता है, तो वस्तुओं में नहीं हैं स्मृति अभी तक प्रस्ताव परिणाम के माध्यम से पुनरावृत्त करता है, लेकिन एक समय में केवल एक वस्तु प्राप्त कर रहा है। queryIEnumerator का उपयोग करता है, जिसमें Reset() और MoveNext() है। Foreach MoveNext() प्रत्येक राउंड को तब तक कॉल करता है जब तक कोई और परिणाम न हो।

संबंधित मुद्दे