2010-03-03 13 views
6

एक लिंक क्वेरी में अभिव्यक्ति में उत्तीर्ण होना सिंटैक्स के आधार पर अलग-अलग व्यवहार करता है, और मुझे आश्चर्य है कि ऐसा क्यों है।लिंक जहां कीवर्ड बनाम। एक्सटेंशन और अभिव्यक्ति पैरामीटर

चलो कहते हैं कि मैं इस बहुत सामान्य समारोह करते हैं

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause) 

निम्नलिखित कार्यान्वयन काम करता है उम्मीद

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause) 
{ 
    return (from c in _ctx.Companies.Where(whereClause) select c); 
} 

के रूप में लेकिन यह अगले कार्यान्वयन (प्रतिनिधि 'System.Func' संकलन नहीं करता नहीं ले 1 तर्क)

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause) 
{ 
    return (from c in _ctx.Companies where whereClause select c); 
} 

जाहिर है मैं केवल पहले सिंटैक्स का उपयोग कर सकता हूं, लेकिन मैं बस सोच रहा था कि संकलक कहां से कीवर्ड के समान व्यवहार का व्यवहार नहीं करता है?

धन्यवाद, थॉमस

उत्तर

3

के मानदंड को बदलना वाक्य रचना कर सकते हैं दूसरे के लिए मजबूर करने एक बुलियन अभिव्यक्ति नहीं है। इस recitify के लिए, आपको कहना

from c in _ctx.Companies where whereClause.Compile()(c) select c; 

ध्यान दें कि यदि whereClause थे एक Func<Company, bool> आप

from c in _ctx.Companies where whereClause(c) select c; 

ध्यान दें कि

from x in e where f 

के साथ भाग मिल सकता है में संकलक द्वारा यंत्रवत् अनुवाद किया है है

(from x in e).Where(x => f) 

मैं यांत्रिक रूप से कहता हूं क्योंकि यह विधि कॉल आदि की वैधता की जांच करने के लिए कोई अर्थपूर्ण विश्लेषण किए बिना इस अनुवाद को निष्पादित करता है। यह चरण बाद में सभी प्रश्न अभिव्यक्तियों का अनुवाद LINQ विधि-invocation अभिव्यक्तियों में किया गया है।

विशेष रूप से,

from c in _ctx.Companies where whereClause select c 

_ctx.Companies.Where(c => whereClause).Select(c) 

जो स्पष्ट रूप से अतर्कसंगत है अनुवाद किया है।

कारण यह है कि

from c in _ctx.Companies.Where(whereClause) select c 

कानूनी है, क्योंकि IEnumerable<Company>.Where एक अधिभार एक Func<Company, bool> को स्वीकार है और वहाँ एक Func<Company, bool> के लिए एक Expression<Func<Company, bool>> से एक अंतर्निहित रूपांतरण है।

private IEnumerable<Company> 
    GetCompanies(Expression<Func<Company, bool>> whereClause) 
{ 
    return _ctx.Companies.Where(whereClause); 
} 

आप LINQ सिंटैक्स का उपयोग करते हैं, तो where खंड में कोड एक Expression<> है, जो एक कोड पेड़ का प्रतिनिधित्व करता है में अनुवाद किया जाता है:

+0

यदि आप Func अभिव्यक्ति > के बजाय तर्क के रूप में स्वीकार करना चाहते थे, तो आप पैरामीटर प्रकार के रूप में का उपयोग कर सकते थे। –

+0

हाँ यह केवल 'कहां' मतभेदों पर ध्यान केंद्रित करने के लिए एक सरलीकृत उदाहरण है। अभिव्यक्ति > का उपयोग करने का कारण यह है कि मैं चाहता हूं कि डेटा बेस पर कहां निष्पादित किया जाए, स्मृति में नहीं। –

0

अंतर यह है कि एसक्यूएल की तरह में जहां यह अभिव्यक्ति bool का आकलन करती है कि उम्मीद है। लेकिन जहां विधि में अभिव्यक्ति का प्रकार प्रतिनिधि हो सकता है।

काम करने के लिए आप

from identifier in expression where boolean-expression select expression 

whereClausewhereClause.Compile()(c) को बदलने के लिए या (पूरा व्याकरण को सरल बनाने) एक where खंड को शामिल एक प्रश्न अभिव्यक्ति के लिए Func<Company, bool> whereClause और whereClause(c)

2

आप वास्तव में पूरी बात को छोटा कर सकते हैं। जब आप Expression<Func<Customer, bool>> स्वीकार करते हैं, तो आप कह रहे हैं कि आपकी विधि कोड पेड़ स्वीकार करती है, जिसे संकलक द्वारा सी # कोड से परिवर्तित किया जाता है।

चूंकि आपके पास पहले से ही कोड पेड़ है, इसलिए आपको इसे सीधे LINQ वाक्यविन्यास का उपयोग करने के बजाय Where() विधि पर पास करना होगा।

+0

हाँ मुझे एहसास है कि, मेरा उदाहरण यह कहने के लिए बनाया गया था कि अंतर कहाँ होता है, यानी बनाम जहां। धन्यवाद हालांकि :)। –

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