2012-02-17 8 views
5

मैं दाल में एक की आपूर्ति विधि:LinqToSql का उपयोग कर यील्ड रिटर्न डेटाबेस रिकॉर्ड?

public IEnumerable<RecordType> GetRecords() 
{ 
    using (LinqDataContext context = new LinqDataContext()) 
    { 
     var records = context.RecordTable; 

     foreach (RecordType record in records) 
     { 
      yield return record; 
     } 
    } 
} 

उपभोक्ता विधि एक foreach पाश में रिकॉर्ड का उपयोग करता है। इस तरह से मैं RecordTable से सभी रिकॉर्ड्स को कैश नहीं करके स्मृति उपयोग को सहेजना चाहता हूं, क्योंकि LinqToSql दृश्य के पीछे डेटा रीडर का उपयोग करता है।

मैं इस परिदृश्य हालांकि पर दो प्रश्न हैं:

  1. यह सच है कि उपज-लौटने ऊपर दिए गए संसाधनों की बचत होती है और तेजी से एक सरणी के लिए सभी रिकॉर्ड कैशिंग से काम करता है (.ToArray())? एक

  2. डेटा कनेक्शन स्वचालित रूप से ठीक से बंद किया जाएगा (मैं using बयान मतलब) यदि कोई त्रुटि लेने वाली विधि की foreach पाश अंदर हो जाएगा या अगर लेने वाली विधि (बीच में foreach पाश टूट जाएगा की तरह पाया आवश्यक रिकॉर्ड और break)?

उत्तर

3

एक मूल क्वेरी को क्रियान्वित करने के मामले में, यह कर सकते हैं इस तरह से काम करें (निश्चित रूप से यह संभव है) - हालांकि, नग्न Table<T> से पूछताछ के मामले में, यह हो सकता है कि यह सभी बफर पहले हो; आप शायद पुनरावृत्ति के दौरान गिनती, या एक निशान चलने की कोशिश कर सकते हैं। इस मामले में मैं संदिग्ध यह पहले बफर करेगा।

पुन बंद कर दिया: वह भी निर्भर करता है, पी किसी foreach का उपयोग कर रहा है, तो हाँ: foreach के बाद से स्पष्ट रूप से finally के माध्यम से इटरेटर disposes। तथापि! यह गारंटी नहीं है अगर कोई करता है, उदाहरण के लिए (बहुत शरारती और ढीला) के लिए:

var iter = yourData.GetEnumerator(); 
if(iter.MoveNext()) { 
    Console.WriteLine(iter.Current.Name); // first record of, say, 20 
} 
// and don't dispose the iterator == bad 
तो

के बाद से इटरेटर नहीं एक: प्राप्त निपटाए, ख: खुद को थका, और ग: दुर्घटना नहीं है, यह ठीक से बंद नहीं होगा (उन 3 शर्तों में से कोई भी इसे ठीक से बंद कर देगा)। जोर: यह एक रोगजनक मामला है: आम तौर पर यह कहना सुरक्षित है कि "यह बंद हो जाएगा, हां"।

यदि आप चाहते हैं गारंटी गैर बफरिंग, ध्यान दें है कि "व्यवसायिक" आप निर्धारित करते हैं कि, bufferedfalse रहे हैं:

IEnumerable<Customer> customers = connection.Query<Customer>(
     "select * from Customer", buffered: false); 

(यह भी मानकों आदि संभाल कर सकते हैं)

3

1) yield जरूरी तेजी से सभी मूल्यों को पाने के लिए नहीं होगा, लेकिन यह कोड परिणामों से निपटने शुरू करने के लिए इससे पहले कि डेटाबेस सभी परिणाम वापस आ गया है की अनुमति होगी। यही है, उपज तुरंत दिखाई देने वाले पहले परिणाम देता है, जबकि ToArray() को लौटने से पहले सभी परिणामों को दिखाने के लिए इंतजार करना पड़ता है। बेशक, अगर अंतर्निहित प्रदाता बफरिंग या अन्य कारणों से एक बार में सभी परिणामों को वापस कर देते हैं, तो इससे कोई फर्क नहीं पड़ता है।

2) हाँ, using LinqDataContext की कोई बात नहीं निपटान होगा कि कैसे आप ब्लॉक का उपयोग से बाहर निकलें (अपवाद/रिटर्न/ब्रेक/...)

+1

वास्तव में, 2 "जब तक फोन करने वाले ठीक से बर्ताव करता है" है - यह सख्ती से नहीं है के रूप में "गारंटी" अधिकांश के रूप में 'using' –

+0

@MarcGravell मैं तुम्हारे बारे में बात कर रहे हैं नहीं (सही) संभालने हूँ कर रहे हैं पूर्ण संख्यात्मक गणना, या क्या मुझे कुछ और याद आ रही है? –

+0

हां, मैन्युअल रूप से इटेटरेटर चल रहा है, और इसे गलत तरीके से कर रहा है। 'Foreach' का उपयोग करते समय यह कोई समस्या नहीं है, जो सबसे अधिक लोग उपयोग करेंगे। –

2
  1. इटरेटर का आलसी मूल्यांकन किया जाएगा। यह पहली वस्तु खींच जाएगा और उसके बाद उपभोक्ता को "उपज" देगा।प्रदर्शन प्रभाव इस बात पर निर्भर करेगा कि LinqDataContext कैसे कार्यान्वित किया गया है (यह आंतरिक रूप से कैश कर सकता है)। ToArray(), या ToList() का उपयोग करना, आगे बढ़ने से पहले सभी तत्वों को LinqDataContext से बाहर कर देगा। इसलिए, ToArray() का उपयोग करके आप कुछ भी उपज नहीं करेंगे जब तक कि LinqDataContext ने प्रत्येक तत्व को वापस नहीं किया है। चाहे वह इष्टतम है या नहीं, आप पर निर्भर है।
  2. हां, "उपयोग" ठीक से लागू किया जाएगा।