2009-01-19 9 views
11

कल्पना कीजिए मैं निम्नलिखित है: प्रलेखन के अनुसारकैसे LINQ एक बयान का उपयोग करने में निष्पादन स्थगित करता है जब

private IEnumerable MyFunc(parameter a) 
{ 
    using(MyDataContext dc = new MyDataContext) 
    { 
     return dc.tablename.Select(row => row.parameter == a); 
    } 
} 

private void UsingFunc() 
{ 
    var result = MyFunc(new a()); 

    foreach(var row in result) 
    { 
     //Do something 
    } 
} 

जब तक मैं वास्तविक परिणाम है, जो foreach पर लाइन में होता है गणना LINQ निष्पादन स्थगित होगा । हालांकि, उपयोग करने वाले कथन को ऑब्जेक्ट को MyFunct() पर कॉल के अंत में विश्वसनीय रूप से एकत्रित करने के लिए मजबूर होना चाहिए।

क्या वास्तव में होता है, जब disposer रन और/या परिणाम चलेगा?

केवल बात मैं के बारे में सोच सकते हैं आस्थगित निष्पादन, संकलन समय पर की जाती है ताकि वास्तविक कॉल, foreach की पहली पंक्ति के लिए संकलक द्वारा ले जाया जाता है सही ढंग से प्रदर्शन करने के लिए का उपयोग कर के कारण, लेकिन foreach तक नहीं चला है लाइन? वहाँ एक गुरु वहाँ बाहर मदद कर सकता है?

संपादित करें: नोट: यह कोड काम करता है, मुझे बस समझ में नहीं आता है।

मैंने कुछ पढ़ा और मुझे अपने कोड में एहसास हुआ कि मैंने ToList() एक्सटेंशन विधि कहा है जो निश्चित रूप से परिणाम को दर्शाता है। वास्तविक प्रश्न के उत्तर के लिए चुने हुए उत्तर का व्यवहार बिल्कुल सही है।

किसी भी भ्रम के लिए खेद है।

+0

अच्छा सवाल है। मुझे इस पर बमबारी कर दी गई है .. एक प्रयोग (डेटाकॉन्टेक्स्ट) शानदार रूप से – Gishu

+0

को उड़ाता है मुझे ऑब्जेक्ट डिस्प्ले अपवाद "डेटा कॉन्टेक्स्ट का निपटान करने के बाद एक्सेस किया जाता है।" जब मैं कोशिश करता हूँ। क्या आपका MyDataContext LINQ डिजाइनर से स्वत: जेनरेट किया गया DataContext है? क्या यह डेटाकॉन्टेक्स्ट से प्राप्त होता है? –

+0

मैं तीसरी धारणा: यदि आप "उपयोग" का उपयोग करके अपने डेटाकॉन्टेक्स्ट का निपटान करते हैं, तो आप बाद में डेटाकॉन्टेक्स्ट का उपयोग करने का प्रयास करते समय एक रनटाइम अपवाद प्राप्त करेंगे। मुझे पता है मैंने इसे किया है। –

उत्तर

12

मैं बस काम नहीं करने के लिए है कि उम्मीद करेंगे; Select टाल रहा है, इसलिए कोई डेटा इस बिंदु पर भस्म कर दिया गया है। हालांकि, चूंकि आपने डेटा-संदर्भ का निपटारा किया है (MyFunc छोड़ने से पहले), यह कभी भी डेटा प्राप्त नहीं कर पाएगा। डेटा-संदर्भ को विधि में पास करने का एक बेहतर विकल्प है, ताकि उपभोक्ता जीवनकाल चुन सके। इसके अलावा, मैं लौटने IQueryable<T> करने की सलाह देते हैं ताकि उपभोक्ता "रचना" परिणाम कर सकते हैं (यानी आदि जोड़ने OrderBy/Skip/Take/Where, और यह अंतिम क्वेरी प्रभाव पड़ता है):

// this could also be an instance method on the data-context 
internal static IQueryable<SomeType> MyFunc(
    this MyDataContext dc, parameter a) 
{ 
    return dc.tablename.Where(row => row.parameter == a); 
} 

private void UsingFunc() 
{ 
    using(MyDataContext dc = new MyDataContext()) { 
     var result = dc.MyFunc(new a()); 

     foreach(var row in result) 
     { 
      //Do something 
     } 
    } 
} 

अद्यतन: यदि आप (टिप्पणियां) निष्पादन को स्थगित नहीं करना चाहते हैं (यानी आप कॉलर डेटा-संदर्भ से निपटना नहीं चाहते हैं), तो आपको परिणामों का मूल्यांकन करने की आवश्यकता है। आप परिणाम पर .ToList() या .ToArray() बुला मूल्यों बफ़र होना करके ऐसा कर सकते।

private IEnumerable<SomeType> MyFunc(parameter a) 
{ 
    using(MyDataContext dc = new MyDataContext) 
    { 
     // or ToList() etc 
     return dc.tablename.Where(row => row.parameter == a).ToArray(); 
    } 
} 

आप इसे इस मामले में टाल रखने के लिए चाहते हैं, तो आप एक "iterator ब्लॉक" का उपयोग करने की जरूरत है:

private IEnumerable<SomeType> MyFunc(parameter a) 
{ 
    using(MyDataContext dc = new MyDataContext) 
    { 
     foreach(SomeType row in dc 
      .tablename.Where(row => row.parameter == a)) 
     { 
     yield return row; 
     } 
    } 
} 

यह अब डेटा-प्रसंग के आसपास गुजर बिना टाल रहा है।

+0

मैं डेटाबेस लॉजिक से डेटाबेस संचालन को रखने की कोशिश कर रहा हूं, इसलिए मैं डेटाकॉन्टेक्स्ट के चारों ओर पास नहीं होने की कोशिश कर रहा हूं। मैं चाहता हूं कि इन कार्यों से सूचियां, संख्यात्मक और स्केलर हों। – Spence

+0

अद्यतन देखें, फिर –

+0

क्या यह हर बार डेटाबेस को हिट करेगा? या यह क्वेरी करेगा और फिर प्रत्येक मूल्य वापस लाएगा? – Spence

8

मैं सिर्फ इस समस्या here के लिए एक और टाल-निष्पादन समाधान तैनात, इस नमूना कोड सहित:

IQueryable<MyType> MyFunc(string myValue) 
{ 
    return from dc in new MyDataContext().Use() 
      from row in dc.MyTable 
      where row.MyField == myValue 
      select row; 
} 

void UsingFunc() 
{ 
    var result = MyFunc("MyValue").OrderBy(row => row.SortOrder); 
    foreach(var row in result) 
    { 
     //Do something 
    } 
} 

Use() विस्तार विधि अनिवार्य रूप से एक आस्थगित using ब्लॉक की तरह कार्य करता है।

+0

मैंने पहले ही जवाब स्वीकार कर लिया है लेकिन यह सोचने का वास्तव में निफ्टी तरीका है। उपयोग() विस्तार विधि। आप इस तरह के उत्तर के लिए +1 से अधिक के लायक हैं। – Spence

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