LINQ में कई "ऑर्डर"


1582

मेरे पास दो टेबल हैं, moviesऔर categories, मुझे पहले श्रेणी और फिर नाम से क्रमबद्ध सूची मिलती है ।

मूवी टेबल में तीन कॉलम आईडी, नाम और श्रेणी है । श्रेणी तालिका में दो कॉलम आईडी और नाम हैं

मैंने निम्नलिखित की तरह कुछ करने की कोशिश की, लेकिन यह काम नहीं किया।

var movies = _db.Movies.OrderBy( m => { m.CategoryID, m.Name })

यहाँ यह काम क्यों नहीं कर सकता है: कोष्ठकों में लंबोदर अभिव्यक्ति को एक मान लौटाना है जिसका उपयोग वस्तुओं को ऑर्डर करने के लिए किया जा सकता है: m.CategoryID एक संख्या है जिसका उपयोग वस्तुओं को ऑर्डर करने के लिए किया जा सकता है। लेकिन "m.CategoryID, m.Name" का इस संदर्भ में कोई मतलब नहीं है।
चिकोडोरो

9
.ThenBy क्या आप खोज रहे हैं?
eka808

अगर किसी भी तरह से आप उन्हें नीचे उतरते क्रम में क्रमबद्ध करना चाहते हैं तो यहां जाने का रास्ता है।
आरबीटी

जवाबों:


2831

यह आपके लिए काम करना चाहिए:

var movies = _db.Movies.OrderBy(c => c.Category).ThenBy(n => n.Name)

4
पाठ्यक्रम के उत्तर के लिए धन्यवाद ... लेकिन इसके बजाय Var movies = _db.Movies.Orderby(c => c.Category).ThenBy(n => n.Name) अगर मैं Var movies = _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name) 2 बार "आदेश का उपयोग करता हूं" तो परिणाम अलग क्यों है?

147
@ देवेन्द्र, परिणाम अलग है क्योंकि दूसरा "ऑर्डरबाय" संग्रह पर काम करता है जो पहले "

68
पृथ्वी पर कैसे मैं इस समय के बारे में जानने के बिना चले गए हैं ThenBy? ( संपादित करें: ऐसा लगता है कि इसे .NET 4.0 में पेश किया गया था, जो बताता है कि यह मेरे अतीत से कैसे फिसल गया।)
जॉर्डन ग्रे

13
LINQ जोड़े जाने के बाद से यह वहाँ है। यह उत्तर .NET 4.0 है।
नाथन डब्ल्यू

10
हां, मैंने निष्कर्ष निकाला कि बहुत जल्दबाजी में 3.5 प्रलेखन संस्करण में संस्करण ड्रॉपडाउन पर आधारित नहीं है ; मुझे संस्करण की जानकारी के लिए सभी तरह से नीचे देखना चाहिए था। सुधारों के लिए धन्यवाद। :)
जॉर्डन ग्रे

594

गैर-लैम्ब्डा, क्वेरी-सिंटैक्स LINQ का उपयोग करके, आप यह कर सकते हैं:

var movies = from row in _db.Movies 
             orderby row.Category, row.Name
             select row;

[टिप्पणी को संबोधित करने के लिए संपादित करें] सॉर्ट क्रम को नियंत्रित करने के लिए, कीवर्ड का उपयोग करें ascending(जो डिफ़ॉल्ट है और इसलिए विशेष रूप से उपयोगी नहीं है) या descending, जैसे:

var movies = from row in _db.Movies 
             orderby row.Category descending, row.Name
             select row;

1
इस सिंटैक्स में अवरोही और गैर के बीच पलटने का कोई तरीका नहीं है?
ईधव

1
दरअसल, आपका जवाब इसके बराबर है _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name)। अधिक सही हैfrom row in _db.Movies orderby row.Category descending orderby row.Name select row
Lodewijk

9
@Lodewijk: मेरा मानना ​​है कि आपके पास बिल्कुल पीछे की तरफ है। आपका उदाहरण पंक्ति को समाप्त कर देगा। नाम प्राथमिक स्तंभ और पंक्ति होने के नाते। श्रेणी माध्यमिक, जो के बराबर है _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name)। आपके द्वारा प्रदान किए जाने वाले दो स्निपेट्स एक-दूसरे के समतुल्य हैं, ओपी के लिए नहीं।
स्कॉट स्टाफोर्ड

6
Linq के लिए SQL सिंटैक्स का उपयोग करने के लिए केवल नकारात्मक पक्ष यह है कि सभी फ़ंक्शन समर्थित नहीं हैं, सबसे अधिक लेकिन सभी नहीं
यहोशू जी

74

नया जोड़ें":

var movies = _db.Movies.OrderBy( m => new { m.CategoryID, m.Name })

जो मेरे बॉक्स पर काम करता है। यह कुछ ऐसा करता है जिसे सॉर्ट करने के लिए इस्तेमाल किया जा सकता है। यह दो मानों के साथ एक वस्तु देता है।

इसी तरह, लेकिन एक संयुक्त स्तंभ द्वारा छांटने के लिए अलग, निम्नानुसार है।

var movies = _db.Movies.OrderBy( m => (m.CategoryID.ToString() + m.Name))

21
संख्याओं के लिए उपयोग करते समय सावधान रहें।
WoF_Angel

7
आप अपनी जरूरत के हिसाब से ऑर्डरबायस्केंडिंग और फिरबाय, या ऑर्डरबाय और फिरबाइंडस्केडिंग का उपयोग कर सकते हैं।
अली शाह अहमद

6
मुझे पूरा यकीन है कि .OrderBy( m => new { m.CategoryID, m.Name })और .OrderBy( m => new { m.Name, m.CategoryID })इच्छित प्राथमिकता का सम्मान करने के बजाय उसी परिणाम का उत्पादन करेंगे। यह कभी-कभी आपको वह आदेश देता हुआ दिखाई देगा जिसे आप विशुद्ध रूप से संयोग से चाहते हैं। इसके अतिरिक्त m.CategoryID.ToString() + m.Nameयदि श्रेणीआईडी ​​एक है तो गलत आदेश देगा int। उदाहरण के लिए, आईडी = 123, नाम = 5times के साथ कुछ आईडी के बाद दिखाई देगा = 1234, नाम = पहले के बजाय कुछ। यह स्ट्रिंग तुलना करने के लिए भी अक्षम नहीं है जहां अंतर तुलना हो सकती है।
एरोनल्स

7
जब मैं एक अनाम प्रकार से ऑर्डर करने की कोशिश करता हूं, तो मुझे संदेश के साथ एक तर्क प्राप्त होता है "कम से कम एक वस्तु को IComparable को लागू करना चाहिए।" मैं दूसरों को ऐसा करते समय एक तुलनित्र घोषित करने के लिए देखता हूं। Stackoverflow.com/questions/10356864/… देखें ।
रॉबर्ट गौलैंड

4
यह बिलकुल गलत है। एक नए अनाम प्रकार से ऑर्डर करना जिसके पास कोई ICompariable कार्यान्वयन नहीं है, काम नहीं कर सकता है, क्योंकि किसी अनाम प्रकार के गुणों के लिए ऑर्डर नहीं है। यह नहीं पता होगा कि कैटिगरी को पहले क्रमबद्ध करना है या पहले नाम, अकेले अगर वे विपरीत क्रम में क्रमबद्ध किए जाने थे।
ट्राइंको

29

कंसोल के लिए DataContext पर SQL गतिविधि लॉग करने के लिए अपने DataContext पर निम्न पंक्ति का उपयोग करें - फिर आप देख सकते हैं कि डेटाबेस से आपके linq स्टेटमेंट का अनुरोध क्या है:

_db.Log = Console.Out

निम्नलिखित LINQ बयान:

var movies = from row in _db.Movies 
             orderby row.CategoryID, row.Name
             select row;

तथा

var movies = _db.Movies.OrderBy(m => m.CategoryID).ThenBy(m => m.Name);

निम्नलिखित एसक्यूएल का उत्पादन करें:

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].CategoryID, [t0].[Name]

जबकि, Linq में एक ऑर्डरबी को दोहराते हुए, परिणामी SQL आउटपुट को उल्टा करने के लिए प्रकट होता है:

var movies = from row in _db.Movies 
             orderby row.CategoryID
             orderby row.Name
             select row;

तथा

var movies = _db.Movies.OrderBy(m => m.CategoryID).OrderBy(m => m.Name);

निम्न एसक्यूएल का उत्पादन करें (नाम और कैटिगरी स्विच किए जाते हैं):

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].[Name], [t0].CategoryID

24

मैंने कुछ विस्तार विधियाँ (नीचे) बनाई हैं ताकि आपको चिंता न हो कि क्या कोई IQueryable पहले से ही ऑर्डर किया गया है या नहीं। यदि आप कई गुणों द्वारा ऑर्डर करना चाहते हैं तो इसे निम्नानुसार करें:

// We do not have to care if the queryable is already sorted or not. 
// The order of the Smart* calls defines the order priority
queryable.SmartOrderBy(i => i.Property1).SmartOrderByDescending(i => i.Property2);

यह विशेष रूप से तब उपयोगी होता है जब आप क्रमबद्ध तरीके से, क्रमबद्ध करने के लिए गुणों की एक सूची से बनाते हैं।

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

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

    public static IQueryable<T> SmartOrderBy<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable<T>;
            return orderedQuery.ThenBy(keySelector);
        } else {
            return queryable.OrderBy(keySelector);
        }
    }

    public static IQueryable<T> SmartOrderByDescending<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable<T>;
            return orderedQuery.ThenByDescending(keySelector);
        } else {
            return queryable.OrderByDescending(keySelector);
        }
    }
}

1
यह उत्तर सोना है! मैं इस पोस्ट के उत्तर के साथ queryable.IsOrdered () के लिए चेक को संयोजित करूँगा, एक एकल विधि है जो एक तरह की दिशा लेती है: stackoverflow.com/questions/388708
SwissCoder

1
इस तरह Linq कार्यान्वयन को पहले स्थान पर जाना चाहिए! ऑर्डरबाय बुरी तरह से डिज़ाइन किया गया है ...
एंड्रीज मार्टिना

1
@Marie आप स्पष्ट रूप से उपयोग के मामले को समझ नहीं पाए हैं। आप उदाहरण के लिए गुणों की सूची से गतिशील रूप से एक ऑर्डर कैसे बनाते हैं? यही एकमात्र रास्ता है। कृपया नीचे और पुनर्विचार न करें। धन्यवाद।
sjkm

काफी उचित। मुझे अभी भी लाभ नहीं दिखाई दे रहा है लेकिन मैं अपना वोट वापस लूंगा
मैरी

होगा के साथ इस कामnullable datetime
aggie

16

LINQ का उपयोग करने के लिए कम से कम एक और तरीका है, हालाँकि यह सबसे आसान नहीं है। आप इसे उस OrberBy()विधि का उपयोग करके कर सकते हैं जो एक का उपयोग करता है IComparer। सबसे पहले आप एक लागू करने की आवश्यकता IComparerके लिए Movieइस तरह वर्ग:

public class MovieComparer : IComparer<Movie>
{
    public int Compare(Movie x, Movie y)
    {
        if (x.CategoryId == y.CategoryId)
        {
            return x.Name.CompareTo(y.Name);
        }
        else
        {
            return x.CategoryId.CompareTo(y.CategoryId);
        }
    }
}

फिर आप निम्न सिंटैक्स वाली फ़िल्में ऑर्डर कर सकते हैं:

var movies = _db.Movies.OrderBy(item => item, new MovieComparer());

यदि आपको किसी एक आइटम के अवरोही क्रम को स्विच करने की आवश्यकता है Compare() , तो MovieComparerतदनुसार x और y को विधि के अंदर स्विच करें ।


1
मुझे यह पसंद है कि तब से अधिक सामान्य होने के बाद से आप तुलना के साथ अजीब चीजें कर सकते हैं, जिनमें अलग-अलग एल्गोरिदम के साथ वस्तुओं की तुलना करने के लिए तैयार हैं। तत्कालीन सीखने से पहले यह मेरे पसंदीदा समाधान से बेहतर है जो एक ऐसा वर्ग तैयार करना था जो IComparable इंटरफ़ेस को लागू करता है।
गेरार्ड ओपिल सेप

1
2012 के बाद से (.NET संस्करण 4.5) आपको MovieComparerस्वयं एक वर्ग बनाने की आवश्यकता नहीं है ; इसके बजाय आप कर सकते हैं _db.Movies.OrderBy(item => item, Comparer<Movie>.Create((x, y) => { if (x.CategoryId == y.CategoryId) { return x.Name.CompareTo(y.Name); } else { return x.CategoryId.CompareTo(y.CategoryId); } }));। बेशक, यदि आप तर्क को एक अभिव्यक्ति के रूप में लिखना पसंद करते हैं if... के बजाय else, तो लमडा (x, y) => exprसरल हो सकता है।
जेपी स्टिग नील्सन

3

यदि सामान्य रिपॉजिटरी का उपयोग करें

> lstModule = _ModuleRepository.GetAll().OrderBy(x => new { x.Level,
> x.Rank}).ToList();

अन्य

> _db.Module.Where(x=> ......).OrderBy(x => new { x.Level, x.Rank}).ToList();

1
बेनामी अभिव्यक्तियों को स्थानीय रूप से इकाई रूपरेखा कोर द्वारा पार्स किया जाएगा। LINQ अभिव्यक्ति का अनुवाद नहीं किया जा सकता है और इसका स्थानीय स्तर पर मूल्यांकन किया जाएगा।
अल्लेप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.