2011-12-14 28 views
20

क्या यह जानने का कोई तरीका है कि IQueryable<T> का आदेश दिया गया है (OrderBy या OrderbyDescending का उपयोग कर)?यह निर्धारित करें कि एक IQueryable <T> का आदेश दिया गया है या नहीं

तो मुझे पता है कि संग्रह पर OrderBy या ThenBy पर कॉल करना है या नहीं।

IQueryable<Contact> contacts = Database.GetContacts(); 

मैं contacts is IOrderedQueryable<Contact> की कोशिश की, लेकिन यह हमेशा सच है।

संपादित करें: मैंने अभी अपना उदाहरण बदल दिया है, पिछला कोई वास्तव में मेरा बिंदु नहीं दिखा रहा था। मान लें कि GetContacts इकाई फ्रेमवर्क का उपयोग करता है और बस तालिका के सभी रिकॉर्ड देता है।

बाद में, मैं contacts पर कई फ़ंक्शन लागू करता हूं, मुझे नहीं पता कि ये कार्य क्या करते हैं। वे IQueryable<Contact> को सॉर्ट या फ़िल्टर कर सकते हैं।

जब मुझे संग्रह वापस मिल जाता है, तो मुझे इसे एक बार फिर क्रमबद्ध करने की आवश्यकता होती है। ऐसा करने के लिए, मुझे यह जानने की ज़रूरत है कि मुझे OrderBy, या ThenBy पर कॉल करने की आवश्यकता है या नहीं। तो अगर मैं पहले ही सॉर्ट कर चुका हूं तो मैं पूरे संग्रह को पुन: व्यवस्थित नहीं करता हूं।

+0

आप 'IQueryable' के दायरे में रह रहे हैं, आप चिंता करने की जरूरत है यहाँ है कि मैं क्या के साथ आया है? मेरा मतलब यह है कि, अतिरिक्त 'ओडरबी' का परिणाम अंतर्निहित डेटा स्रोत पर प्रदाता द्वारा वास्तव में निष्पादित किए गए किसी भी बदलाव में नहीं हो सकता है। – AakashM

+0

@AakashM, अगर मैं पहले से क्रमबद्ध 'IQueryable' पर' ऑर्डरबी 'कहता हूं तो मैं उस तरह से हार जाता हूं। मैं बस इसमें जोड़ना चाहता हूं। –

+0

मैं वास्तव में सोच रहा था कि आप perf के बारे में चिंता कर रहे थे। हमेशा 'ThenBy' का उपयोग करने के बारे में कैसे? – AakashM

उत्तर

2

संक्षिप्त उत्तर नहीं है, क्वेरी योग्य वर्ग ध्वज बनाए रखता है या संग्रह को सॉर्ट किया गया है और न ही इस तरह के तरीके को करने के लिए किस विधि का उपयोग किया जा सकता है।

http://msdn.microsoft.com/en-us/library/system.linq.queryable.aspx

+7

फिर, कैसे [ '.Skip'] (http://msdn.microsoft.com/en-us/library/bb357513.aspx) में सक्षम है करने के लिए [एक अपवाद फेंक] (http://stackoverflow.com/questions/ 225481/कैसे-एक-ऑब्जेक्ट-इन-ऑब्जेक्ट-ए-ऑब्जेक्ट-एक्सप्रेशन-पेड़) के लिए कैसे करें जब आप इसे एक अनियंत्रित ईएफ संग्रह पर उपयोग करते हैं? –

+1

मुझे नहीं लगता .किप एक अपवाद फेंक देता है। अंतर्निहित प्रदाता एक अपवाद फेंकता है जब यह * पूरे * IQueryable से एक क्वेरी बनाने का प्रयास करता है। –

+1

यह सच है कि इस तरह का ध्वज नहीं है, लेकिन यह बताना संभव है कि ऑर्डरिंग विधि कहलाती है या नहीं। [मेरा जवाब] देखें (http://stackoverflow.com/a/31252271/964514)। –

1

आप कभी भी यह नहीं जान पाएंगे कि ऑब्जेक्ट्स को सही तरीके से आदेश दिया गया है, जब तक कि आप स्वयं को ऑर्डर करने की जांच न करें। आपका उदाहरण यह देखना आसान है कि उन्हें आदेश नहीं दिया गया है, क्योंकि संख्याओं का प्राकृतिक क्रम होता है, लेकिन IQueryable एक सामान्य है, जिसका अर्थ यह है कि यह विभिन्न प्रकार की वस्तुओं को संभाल सकता है। उपयोगकर्ता ऑब्जेक्ट्स (फर्स्टनाम, लास्टनाम, डेट स्टार्ट, और लास्टपेडडेट) का ऑर्डर करने का मनमाना क्रम होता है, और इसलिए जिस क्रम में वे वापस आते हैं वह जरूरी नहीं है कि आप जिस ऑर्डर की तलाश कर रहे हों। (जिसे इस तरह के लिए प्राथमिक क्षेत्र माना जाता है? यह आपकी ज़रूरत पर निर्भर करता है।) तो सिद्धांत रूप में, सवाल, "क्या वे आदेश दिए गए हैं" हमेशा "हाँ!" हो सकते हैं जिस ऑर्डर को आप ढूंढ रहे हैं वह सिस्टम की वापसी के मुकाबले काफी अलग हो सकता है।

+0

मेरा उदाहरण सिर्फ यह इंगित करना था कि 'IOrderedQueryable' के साथ परीक्षण हमेशा सत्य हो जाता है। मैं अपने प्रश्न को स्पष्ट करूंगा। –

1

असल में, आप कर सकते हैं।

आपके कोड में पहली समस्या यह है कि आप संग्रह को IQueryable पर ऐसा करने के किसी भी कारण के बिना कास्टिंग कर रहे हैं।

निम्नलिखित स्निपेट:

var numbers = new[] {1, 5, 6, 87, 3}; 
Console.Write(numbers is IOrderedEnumerable<int>); 
var ordered = numbers.OrderBy(c => c); 
Console.Write(ordered is IOrderedEnumerable<int>); 

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

वैसे भी, यदि आप इसे चलाते हैं, तो यह आपको पहले चेक के लिए गलत लगेगा, और दूसरे चेक के लिए ट्रू देगा।

आप IQueryable<T> और IOrderedQueryable<T> के साथ एक ही चीज़ कर सकते हैं जो आप वास्तव में उस प्रकार का उपयोग कर रहे हैं, और इसमें संग्रह कास्टिंग नहीं कर रहे हैं।

+0

क्या होता है यदि गणना में आइटम पहले से ही हो सकता है? –

+3

इस तरह 'dbSet.AsQueryable()' के रूप में हमेशा ऐसा सच वापस आ जाएगी पर 'है जाँच IOrderedQueryable' संग्रह पर काम करने के लिए प्रतीत नहीं होता। – Juri

1

ऑर्डर बाय का उपयोग करने के लिए आप अपनी क्वेरी के ToString() की जांच कर सकते हैं।

जब कोई जुड़ाव होता है IQueryable के ToString प्रारंभिक क्वेरी के प्रारंभ और अंत में parantheses डालता है।इसलिए यदि आपको अंतिम समापन पैराथेस मिलते हैं तो आप जांच सकते हैं कि आपकी बाहरी क्वेरी में ऑर्डर द्वारा ऑर्डर है या नहीं।

private bool isOrdered(IQueryable Data) 
    { 
     string query = Data.ToString(); 

     int pIndex = query.LastIndexOf(')'); 

     if (pIndex == -1) 
      pIndex = 0; 

     if (query.IndexOf("ORDER BY", pIndex) != -1) 
     { 
      return true; 
     } 

     return false; 
    } 

मैं जानता हूँ कि यह बहुत गंदा है लेकिन यह मेरी सभी मामलों में काम करता है और मैं एक असाधारण मामला नहीं सोच सकते हैं।

+0

मुझे आपका समाधान पसंद है, गंदे लेकिन एक आकर्षण की तरह काम करता है! –

16

यह संभव है। यहाँ एक विस्तार विधि है:

public static bool IsOrdered<T>(this IQueryable<T> queryable) 
{ 
    if (queryable == null) 
    { 
     throw new ArgumentNullException("queryable"); 
    } 

    return queryable.Expression.Type == typeof(IOrderedQueryable<T>); 
} 
+0

धन्यवाद, यही वह है जिसे मैंने देखा था। मैं तो बस प्रकार की समानता के बजाय इंटरफ़ेस के कार्यान्वयन के लिए चेक बदल जाएगा ... typeof (IOrderedQueryable ) .IsAssingableFrom (queryable.Expression.Type) – Ondrej

+0

क्या है कि परिवर्तन @Ondrej के क्या लाभ हैं? मैंने यह भी देखा कि ऑर्डरबी सबसे हालिया ऑपरेशन नहीं होने पर न तो काम करता है :( –

2

हाँ आप अगर यह OrderBy/ThenBy तरीकों में से किसी भी कॉल को देखने के लिए IQueryable.Expression पेड़ निरीक्षण कर सकते हैं। ExpressionVisitor से कक्षा प्राप्त करके अभिव्यक्ति के पेड़ों की जांच की जा सकती है।

System.Web में एक आंतरिक OrderingMethodFinder नहीं है - जो आप अनुकूलित कर सकते हैं।

// Adapted from internal System.Web.Util.OrderingMethodFinder http://referencesource.microsoft.com/#System.Web/Util/OrderingMethodFinder.cs 
class OrderingMethodFinder : ExpressionVisitor 
{ 
    bool _orderingMethodFound = false; 

    protected override Expression VisitMethodCall(MethodCallExpression node) 
    { 
     var name = node.Method.Name; 

     if (node.Method.DeclaringType == typeof(Queryable) && (
      name.StartsWith("OrderBy", StringComparison.Ordinal) || 
      name.StartsWith("ThenBy", StringComparison.Ordinal))) 
     { 
      _orderingMethodFound = true; 
     } 

     return base.VisitMethodCall(node); 
    } 

    public static bool OrderMethodExists(Expression expression) 
    { 
     var visitor = new OrderingMethodFinder(); 
     visitor.Visit(expression); 
     return visitor._orderingMethodFound; 
    } 
} 

इतना है कि यह प्रयोग करें:

bool isOrdered = OrderingMethodFinder.OrderMethodExists(myQuery.Expression); 
संबंधित मुद्दे

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