2012-04-12 12 views
8

तक पहुंच के साथ मेरे पास डेटाबेस तालिका Item है और इसे linq-to-sql के साथ एक्सेस करें।गैर स्थैतिक अभिव्यक्ति <Func<X>> 'इस'

मैं आइटम जो सच रिटर्न के लिए एक कस्टम विधि IsSpecial() को परिभाषित कर सकते हैं अगर Item.id का वर्गमूल भी है:

partial class Item 
{ 
    public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0); 
} 

तो मैं एक LINQ करने वाली एसक्यूएल क्वेरी में है कि संपत्ति का उपयोग कर सकते

datacontext.Item.Where(i => i.IsSpecial()) 
:

datacontext.Item.Where(Item.IsSpecial) 
अब सौंदर्य कारणों के लिए

, मैं IsSpecial nonstatic बनाने के लिए और यह इतना संशोधित मैं इसे इस तरह कॉल कर सकते हैं करना चाहते हैं: इस तरह

आदर्श रूप में यह भी बयान के संयोजन की अनुमति होगी, जो ऊपर (कार्य) snytax अनुमति नहीं देता:

datacontext.Item.Where(i => i.IsSpecial() && i.Id >100) 

इस विधि को परिभाषित करने के लिए सही सिंटैक्स क्या है?

यह काम नहीं करता:

partial class Item 
{ 
    public Expression<Func<bool>> IsSpecial = (() => Math.Sqrt(this.Id)%2==0); 
    // 'this' keyword not available in current context 
} 

संपादित करें: मुझे लगता है कि मैं कुछ है कि वाक्य रचना बस

की अनुमति नहीं है के लिए पूछ रहा हूँ शुरू कर रहा हूँ मुझे लगता है मैं कर सकते हैं datacontext.Item.Where(Item.IsSpecial).Where(i => i>100)

+0

BTW 'datacontext.Item। कहां (i => आइटम। विशेष (i)) 'संकलित नहीं होगा। – leppie

+0

आप एक IsSpecial विधि को परिभाषित करने के बजाय Func प्रकार की एक IsSpecial संपत्ति को परिभाषित क्यों कर रहे हैं? या यहां तक ​​कि बस बूल की एक विशेष विशेषता है? –

+0

'datacontext.Item.Where (Item.IsSpecial)' हालांकि संकलित करेगा। – leppie

उत्तर

4
partial class Item 
{ 
    public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0); 
} 

सुझाव: readonly कीवर्ड जोड़ें। ,

datacontext.Item.Where(Item.IsSpecial) 

सही क्योंकि Where प्रकार Expression<Func<Item, bool>>, जो Item.IsSpecial है की एक पैरामीटर स्वीकार करता है:

तो मैं इस तरह की एक LINQ करने वाली एसक्यूएल क्वेरी में है कि संपत्ति का उपयोग कर सकते हैं।

अब सौंदर्य कारणों के लिए, मैं IsSpecial nonstatic बनाने के लिए और यह इतना संशोधित मैं इसे इस तरह कॉल कर सकते हैं करना चाहते हैं:

datacontext.Item.Where(i => i.IsSpecial()) 

कारण यह काम नहीं करता है, क्योंकि IsSpecial नहीं है एक समारोह, यह एक अभिव्यक्ति पेड़ है। () केवल कार्यों पर लागू किया जा सकता है। एक अभिव्यक्ति वृक्ष एक समारोह का वर्णन करता है, लेकिन एक नहीं है। क्योंकि फिर, Where एक अभिव्यक्ति पेड़ पारित हो जाता है,

datacontext.Item.Where(i => (IsSpecial.Compile()) (i)) 

बहरहाल, यह काम नहीं करेगा, और IsSpecial.Compile() वास्तव में नहीं बुलाया जाता है: आप एक असली समारोह expression.Compile() का उपयोग कर बना सकते हैं। LINQ से SQL को SQL में कनवर्ट करने का प्रयास करता है, विफल रहता है क्योंकि यह Expression.Compile को पहचानता नहीं है, और अपवाद फेंकता है।

हालांकि, अगर आप एसक्यूएल के लिए LINQ से पहले (IsSpecial.Compile()) बदल सकते यह देखने के लिए ... थे

कि जहां LINQKit आता है:

यह करने के लिए यह काम कर रहा हो अभिव्यक्ति पेड़ हेरफेर के सिर्फ इतना है कि थोड़ा प्रदान करता है।

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i)) 

.AsExpandable()-फिल्टर पूर्व अभिव्यक्ति को datacontext.Item के चारों ओर एक आवरण बनाता है।

आदर्श रूप में यह भी बयान के संयोजन है, जो ऊपर (कार्य) snytax की अनुमति नहीं है की अनुमति होगी:

datacontext.Item.Where(i => i.IsSpecial() && i.Id >100) 

कोई समस्या नहीं है:

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i) && i.Id > 100) 
+0

यह बहुत ही आशाजनक दिखता है, इसे देखेगा, धन्यवाद! मैं इसके लिए एक और लाइब्रेरी समेत थोड़ा सा संदेह कर रहा हूं, लेकिन लिनकिकिट के लिंक ने मुझे http://tomasp.net/blog/linq-expand.aspx का नेतृत्व किया जो इस समस्या पर अधिक विस्तार से चर्चा करता है – HugoRune

2

के साथ लाइव आप सीधे IsSpecial का उपयोग कर सकते हैं:

partial class Item 
{ 
    public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0); 
} 

datacontext.Item.Where(Item.IsSpecial) 
+0

+1 पहला समाधान वास्तव में संकलित करेगा। हालांकि मैंने उस समय एक ही चीज़ के बारे में टिप्पणी की थी :) – leppie

+0

क्षमा करें, मैंने अपने शुरुआती प्रश्न में वाक्यविन्यास की प्रतिलिपि बनाते समय गड़बड़ कर ली, यही वह है जिसे मैं लिखना चाहता था। आदर्श रूप में मैं इसे कुछ (जैसे वैलीड :) datacontext.Item.Where (i => i.isSpecial() && i.Id> 100 && [अधिक गुण] 'में बदलना चाहता हूं, हालांकि मुझे संदेह है कि मुझे संदेह है जो मैं पूछ रहा हूं वह असंभव है – HugoRune

1

एक निर्माता में IsSpecial असाइनमेंट डालने की कोशिश करो और इसे करने के लिए सभी अन्य निर्माताओं के प्रतिनिधि हैं, या आप एक आंशिक विधि जैसे IsSpecial को अभिव्यक्ति आवंटित करने के लिए OnCreated इस्तेमाल कर सकते हैं। partial class Item

partial void OnCreated() 
{ 
    IsSpecial =() => Math.Sqrt(this.Id)%2==0; 
} 

की अंदर ऐसा करने से हमेशा IsSpecial असाइन करें और "इस" के लिए उपयोग की अनुमति देगा।

+0

यह इस तरह से काम करता है क्योंकि मैं इस तरह अभिव्यक्ति में 'इस' का उपयोग कर सकता हूं। हालांकि लिंक एक अंदरूनी अभिव्यक्ति में पैरामीटर को पार करने का आग्रह करेगा। जहां खंड, इसलिए() => xyz काम नहीं करना चाहिए , इसे (आइटम) => xyz होना चाहिए, जिसका अर्थ है कि मुझे पास पैरामीटर को अनदेखा करना है, और पूरी चीज गन्दा हो जाती है। हालांकि इस सुझाव ने मुझे संबंधित समस्या को हल करने में काफी मदद की, इसलिए धन्यवाद! – HugoRune

+0

@ हूगोरुने लुकिंग आपकी पिछली टिप्पणियों में से कुछ पर, मुझे लगता है * (मुझे वास्तव में कोई जानकारी नहीं है) कि यह एक टिप्पणी के अनुसार काम करेगा जैसा आपने कहा था: 'डेटाैकेंटेक्स्ट.इटम। जहां (i => i.IsSpecial() && मैं।आईडी> 100 && [अधिक गुण] ' – JKor

+0

हाँ, मैंने भी सोचा, लेकिन यह पता चला है कि इस तरह से यह संभव नहीं है। 'इस' मुद्दे को छोड़कर, यह अभी भी काम नहीं करेगा, भले ही मैं 'इस' के बजाय निरंतर उपयोग करता हूं। कारण: IsSpecial एक अभिव्यक्ति वृक्ष है, एक साधारण समारोह या लैम्ब्डा नहीं है। कॉलिंग 'IsSpecial() 'मान्य वाक्यविन्यास नहीं है। 'I => i.Ispecialpecial && i.Id> 100' मान्य वाक्यविन्यास नहीं है, आप इस तरह अभिव्यक्ति पेड़ को संयोजित नहीं कर सकते हैं। भ्रमित बात यह है कि अगर मैं अभिव्यक्ति > के बजाय एक साधारण प्रतिनिधि या फ़ंक्शन का उपयोग करता हूं, तो यह सामान्य लिंक के साथ संकलित और काम करेगा, लेकिन linq-to-sql एक अलग जानवर है – HugoRune