2011-10-26 15 views
6

पर लागू किया गया है, तो मैं कैसे पता लगा सकता हूं कि IQueryable<T> में where फ़िल्टर लागू है या नहीं?पता लगाएं कि IQueryable <T>

इस कोड में, मैं प्रोग्राम के रूप में पता करने के लिए queryFiltered एक where इसे करने के लिए आवेदन किया है और query

IQueryable<Customer> query = Context.Customers; 
IQueryable<Customer> queryFiltered = Context.Customers 
              .Where(c=>c.Name.Contains("ABC")); 
+1

क्यों? अधिक संदर्भ देने से –

उत्तर

9

आप Expression कि IQueryable<T> कार्यान्वयन पर Expression property से दिया जाता है पार्स करने के लिए करना होगा नहीं है है कि जरूरत है ।

आप Queryable.Where method के लिए क्वेरी करने के लिए बुलाया जा रहा है के रूप में आप Expression पेड़ क्रॉल होगा।

यह भी ध्यान रखें कि जब तक Queryable.Where सबसे आम तरीका एक where फिल्टर पता लगाने के लिए होने जा रहा है, क्वेरी सिंटैक्स अन्य कार्यान्वयन के लिए (क्या नामस्थान using directives में किया जाता है पर निर्भर करता है) का इस्तेमाल किया जा करने की अनुमति देता अगर आपके पास ऐसा कुछ है जो Queryable.Where एक्सटेंशन विधि का उपयोग नहीं कर रहा है तो आपको उस स्पष्ट रूप से देखना होगा (या Where विधि के लिए फ़िल्टरिंग की एक और सामान्य विधि का उपयोग करना होगा जो IQueryable<T> लेता है और IQueryable<T> देता है)।

ExpressionVisitor class (pointed out by xanatos के रूप में) Expression पेड़ रेंगने की एक बहुत ही आसान तरीका प्रदान करता है, मैं अत्यधिक अपने Expression पेड़ के प्रसंस्करण के लिए एक आधार के रूप कि दृष्टिकोण का उपयोग करें।

ध्यान दें कि ExpressionVisitor वर्ग कार्यान्वयन कक्षा स्तर पर राज्य को स्टोर और बेनकाब करने की आवश्यकता है। इसके कारण, आंतरिक कक्षाओं को बनाने के लिए यह सर्वोत्तम होगा (आईएमओ) जो एक बार कार्रवाई करते हैं और फिर एक सार्वजनिक विधि है जो हर बार ExpressionVisitor का एक नया उदाहरण बनाता है; इससे उत्परिवर्तनीय स्थिति से निपटने में मदद मिलेगी, और यदि सही तरीके से किया जाता है, तो विधि को थ्रेड-सुरक्षित भी होने की अनुमति होगी (यदि यह आपकी चिंता है)।

3

आप सी # 4.0 का उपयोग कर रहे हैं, तो आप इस नमूना कोड का उपयोग कर सकते हैं: Get all 'where' calls using ExpressionVisitor

यह ExpressionVisitor पर आधारित है। यह भागों को खोजने के लिए IQueryable<T> के विभिन्न तत्वों पर "विज़िट करता है"। यह काफी आसान लगता है।

आप सी # = 3.5 पर हैं, तो आप MSDN के How to: Implement an Expression Tree Visitor प्लस WhereFinder पिछले लिंक से से ExpressionVisitor नमूना (वे सही ढंग से एक साथ काम करने के लिए, बस का परीक्षण)

उपयोग कर सकते हैं कोड का उपयोग करें:

var wf = new WhereFinder(); 
var wheres = wf.GetWhere(query.Expression); 

if (wheres.Any()) 
{ 
    // There are Where in the query! 
} 

आप (सही) कर रहे हैं Rune FS जितना पागल, WereFinder.VisitMethodCall को, if

को
if (expression.Method.Name == "Where" && expression.Method.DeclaringType.FullName == "System.Linq.Queryable") 
बदल
+0

बेहतर उत्तर देने में मदद मिल सकती है, यह मूल रूप से "कहां" नामक एक विधि की खोज करता है जिसे आसानी से अन्य गैर फ़िल्टरिंग विधि द्वारा बेवकूफ़ बना दिया जाता है जिसे –

+0

@RuneFS सही कहा जाता है। लेकिन मुझे लगता है कि आपको मूल क्यू/ए में सुधार पोस्ट करना चाहिए :-) – xanatos

+0

मूल पोस्ट एक विशिष्ट परिदृश्य से संबंधित है जहां अभिव्यक्ति वृक्ष को पहले से जाना जाता है एक ओपी अभिव्यक्ति के रूप में खंडों को निकालने के लिए चाहता है। –

1

सबसे आसान तरीका q.Expression.ToString().Contains(".Where(") पर कॉल करें। जैसा कि आप देख सकते हैं, query.Expression.ToString().Contains(".Where(") झूठा रिटर्न देता है जबकि queryFiltered.Expression.ToString().Contains(".Where(") सत्य देता है।

यदि आप "फ़िल्टरिंग" के रूप में अन्य अभिव्यक्तियों को गिनते हैं तो आपको उससे अधिक जटिलता की आवश्यकता हो सकती है, लेकिन अभिव्यक्ति विज़िटर दृष्टिकोण के साथ भी यह सच है।

इस बारे में कुछ हैकी है जो मैं आपको दूंगा, लेकिन यह बहुत आसान लगता है।

+0

'नया int [] {} .sQueryable()। चुनें (पी =>" .Where (")। ToString()। ("। कहां (")' :-) – xanatos

+0

@xanatos अब यह सिर्फ विपरीत है!) –

+0

@xanatos अभिव्यक्ति विज़िटर दृष्टिकोण ओवरलोड के लिए भी किया जा सकता है, जहां यह ठीक से काम करता है और ऐसा लगता है कि आप फ़िल्टरिंग कर रहे थे जहां वास्तव में आप –

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