2010-06-14 12 views
37

मुझे पता है कि यह राय हो सकती है, लेकिन मैं सर्वोत्तम प्रथाओं की तलाश में हूं।क्या मुझे अपने डीएएल से IENumerable <T> या IQueryable <T> वापस करना चाहिए?

मैं समझता हूँ के रूप में, IQueryable<T>IEnumerable<T> लागू करता है, इसलिए मेरे दाल में, मैं वर्तमान निम्नलिखित की तरह विधि हस्ताक्षर है:

IEnumerable<Product> GetProducts(); 
IEnumerable<Product> GetProductsByCategory(int cateogoryId); 
Product GetProduct(int productId); 

मैं IQueryable<T> यहाँ प्रयोग करना चाहिए?

किसी भी दृष्टिकोण के पेशेवरों और विपक्ष क्या हैं?

ध्यान दें कि मैं भंडार पैटर्न का उपयोग करने पर योजना बना रहा हूँ तो मैं तो जैसे एक वर्ग होगा:

public class ProductRepository { 

    DBDataContext db = new DBDataContext(<!-- connection string -->); 

    public IEnumerable<Product> GetProductsNew(int daysOld) { 
     return db.GetProducts() 
      .Where(p => p.AddedDateTime > DateTime.Now.AddDays(-daysOld)); 
    } 
} 

मैं अपने IEnumerable<T>IQueryable<T> को बदल देना चाहिए? एक या दूसरे के लिए क्या फायदे/नुकसान हैं?

उत्तर

49

यह क्या व्यवहार आप चाहते हैं पर निर्भर करता है।

  • एक IList < टी > रिटर्निंग फोन करने वाले है कि वे डेटा वे का अनुरोध किया है
  • एक IEnumerable < टी > रिटर्निंग के सभी प्राप्त हो गया है बताता है कि वे फोन करने वाले की आवश्यकता होगी बताता है परिणाम पर फिर से शुरू करें और यह आलसी लोड हो सकता है।
  • एक IQueryable < टी > रिटर्निंग फोन करने वाले है कि परिणाम एक LINQ प्रदाता है कि प्रश्नों के कुछ वर्गों संभाल कर सकते हैं के द्वारा समर्थित है, फोन करने वाले पर बोझ डालने के एक performant क्वेरी बनाने के लिए कहता है।

जबकि उत्तरार्द्ध कॉलर को बहुत लचीलापन देता है (माना जाता है कि आपका भंडार पूरी तरह से इसका समर्थन करता है), परीक्षण करने के लिए सबसे कठिन और तर्कसंगत रूप से कम से कम निर्धारिती है।

+0

निकली ने कहा। बुलेट बिंदुओं के साथ संक्षिप्त संक्षेप। – Armstrongest

+0

ठीक है। मैंने हमेशा एक ही बाल्टी में आईएलिस्ट और आईनेमरेबल को लम्बा किया है, लेकिन मुझे यह विचार बेहतर लगता है। – scottm

4

HUUUUGGGE अंतर। मैं इसे थोड़ा सा देखता हूं।

डेटाबेस से हिट करने से पहले आप एक IQueryable बनाते हैं। IQueryable केवल एक उत्सुक फ़ंक्शन (उदाहरण के लिए .Toist()) के बाद डीबी को हिट करता है या आप वास्तव में मूल्यों को खींचने का प्रयास करते हैं। IQueryable = आलसी।

एक आईनेमरेबल तुरंत आपके लैम्बडा को डीबी के खिलाफ निष्पादित करेगा। IEnumerable = उत्सुक।

जिसके लिए रिपोजिटरी पैटर्न के साथ उपयोग करना है, मुझे विश्वास है कि यह उत्सुक है। मैं आमतौर पर आईएलआईएस पास होने को देखता हूं लेकिन किसी और को आपके लिए यह लोहे की आवश्यकता होगी। संपादित करें - आप आमतौर पर IQueryable के बजाय IENumerable देखते हैं क्योंकि आप अपने रिपोजिटरी ए के पीछे परत नहीं चाहते हैं) यह निर्धारित करना कि डेटाबेस हिट कब होगा या बी) रिपोजिटरी

के बाहर जुड़ने के लिए कोई तर्क जोड़ना एक बहुत अच्छा LINQ है वीडियो जो मुझे बहुत पसंद है- यह केवल आईनेमेरेबल v IQueryable से अधिक हिट करता है, लेकिन इसमें वास्तव में कुछ शानदार अंतर्दृष्टि है।

http://channel9.msdn.com/posts/matthijs/LINQ-Tips-Tricks-and-Optimizations-by-Scott-Allen/

+0

बस स्पष्ट होने के लिए, 'उत्पाद रिपोजिटरी' मेरे आवेदन के अंदर बैठा है ... जबकि डीएएल एक अलग परियोजना है जिसका मेरा संदर्भ है। इसलिए मैं अपने ऐप से रिपोजिटरी को कॉल करता हूं, रिपोजिटरी डीएएल प्रोजेक्ट में डीबीडेटा कॉन्टेक्स्ट क्लास को कॉल करता है (जिसमें सभी जेनेरिक विधियां होती हैं), जो डेटाबेस के विरुद्ध कोई भी LinqToSQL करता है। – Armstrongest

+3

IENumerable जरूरी नहीं है। अनगिनत। एक आलसी IENumerable रिटर्न का चयन करें। –

+0

ग्रेट वीडियो। उसके लिए धन्यवाद! – Armstrongest

3

आप IQueryable का उपयोग कर सकते हैं और स्वीकार करते हैं कि कोई ऐसा परिदृश्य बना सकता है जहां SELECT N+1 हो सकता है। यह एक नुकसान है, इस तथ्य के साथ कि आप कोड के साथ समाप्त हो सकते हैं जो आपके भंडार के ऊपर परतों में आपके भंडार कार्यान्वयन के लिए विशिष्ट है। इसका लाभ यह है कि आप प्रतिनिधिमंडल को सामान्य परिचालनों की अनुमति दे रहे हैं जैसे पेजिंग और सॉर्टिंग को आपके श्वसन के बाहर व्यक्त किया जाना चाहिए, इसलिए इस तरह की चिंताओं को कम करना। यदि आपको अन्य डेटाबेस तालिकाओं के साथ डेटा में शामिल होने की आवश्यकता है, तो यह भी अधिक लचीला है, क्योंकि क्वेरी एक अभिव्यक्ति बनी रहेगी, इसलिए इसे क्वेरी में हल करने से पहले जोड़ा जा सकता है और डेटाबेस को हिट करता है।

विकल्प आपके भंडार को लॉक करना है ताकि यह ToList() पर कॉल करके भौतिक सूचियों को वापस कर सके। पेजिंग और सॉर्टिंग के उदाहरण के साथ, आपको अपने भंडार के तरीकों के पैरामीटर के रूप में छोड़ने, लेने और एक प्रकार की अभिव्यक्ति को पास करने की आवश्यकता होगी, और केवल परिणामों की एक विंडो को वापस करने के लिए पैरामीटर का उपयोग करें। इसका मतलब है कि भंडार पेजिंग और सॉर्टिंग की जिम्मेदारी ले रहा है, और आपके डेटा के सभी प्रक्षेपण।

यह एक निर्णय कॉल है, क्या आप अपने आवेदन को linq की शक्ति देते हैं, और भंडार में कम जटिलता है, या आप अपने डेटा का उपयोग नियंत्रित करते हैं। मेरे लिए यह प्रत्येक इकाई से जुड़े प्रश्नों और इकाइयों के संयोजनों पर निर्भर करता है, और जहां मैं उस जटिलता को प्रबंधित करना चाहता हूं।

+0

हमम ... कुछ चीजों के बारे में सोचने के लिए। – Armstrongest

6

इस बारे में सोचने के लिए एक और बात: आपका पेजिंग/सॉर्टिंग समर्थन कहां है? यदि आप अपने भंडार के भीतर पेजिंग समर्थन प्रदान कर रहे हैं, तो IEnumerable<T> लौट रहा है ठीक है। यदि आप अपने भंडार के बाहर पेजिंग कर रहे हैं (जैसे नियंत्रक या सेवा परत में) तो आप वास्तव में IQueryable<T> का उपयोग करना चाहते हैं क्योंकि आप पूरे डेटासेट को पगड़ने से पहले स्मृति में लोड नहीं करना चाहते हैं।

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