IEnumerable <T> / IQueryable <T> पर गतिशील LINQ ऑर्डर


668

डायनेमिक LINQ के लिए VS2008 उदाहरणों में मुझे एक उदाहरण मिला, जो आपको sql- जैसे स्ट्रिंग (जैसे OrderBy("Name, Age DESC"))ऑर्डर करने के लिए) का उपयोग करने की अनुमति देता है । दुर्भाग्य से, इसमें शामिल विधि केवल काम करती है IQueryable<T>। क्या इस कार्यक्षमता को प्राप्त करने का कोई तरीका है IEnumerable<T>?


1
इस तिथि के अनुसार सबसे अच्छा उत्तर, मेरी राय में: System.Linq.Dynamic.Core पुस्तकालय।
शाहीन दोतन

जवाबों:


904

बस इस पुराने में ठोकर खाई ...

गतिशील LINQ लाइब्रेरी के बिना ऐसा करने के लिए, आपको बस नीचे दिए गए कोड की आवश्यकता होगी। यह नेस्टेड गुणों सहित सबसे आम परिदृश्यों को शामिल करता है।

इसके साथ काम करने के लिए IEnumerable<T>आप कुछ रैपर तरीकों को जोड़ सकते हैं AsQueryable- जो कि गुजरते हैं - लेकिन नीचे दिए गए कोड में मुख्य Expressionतर्क है।

public static IOrderedQueryable<T> OrderBy<T>(
    this IQueryable<T> source, 
    string property)
{
    return ApplyOrder<T>(source, property, "OrderBy");
}

public static IOrderedQueryable<T> OrderByDescending<T>(
    this IQueryable<T> source, 
    string property)
{
    return ApplyOrder<T>(source, property, "OrderByDescending");
}

public static IOrderedQueryable<T> ThenBy<T>(
    this IOrderedQueryable<T> source, 
    string property)
{
    return ApplyOrder<T>(source, property, "ThenBy");
}

public static IOrderedQueryable<T> ThenByDescending<T>(
    this IOrderedQueryable<T> source, 
    string property)
{
    return ApplyOrder<T>(source, property, "ThenByDescending");
}

static IOrderedQueryable<T> ApplyOrder<T>(
    IQueryable<T> source, 
    string property, 
    string methodName) 
{
    string[] props = property.Split('.');
    Type type = typeof(T);
    ParameterExpression arg = Expression.Parameter(type, "x");
    Expression expr = arg;
    foreach(string prop in props) {
        // use reflection (not ComponentModel) to mirror LINQ
        PropertyInfo pi = type.GetProperty(prop);
        expr = Expression.Property(expr, pi);
        type = pi.PropertyType;
    }
    Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
    LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);

    object result = typeof(Queryable).GetMethods().Single(
            method => method.Name == methodName
                    && method.IsGenericMethodDefinition
                    && method.GetGenericArguments().Length == 2
                    && method.GetParameters().Length == 2)
            .MakeGenericMethod(typeof(T), type)
            .Invoke(null, new object[] {source, lambda});
    return (IOrderedQueryable<T>)result;
}

संपादित करें: यह और अधिक मजेदार हो जाता है यदि आप उस के साथ मिश्रण करना चाहते हैं dynamic- हालांकि ध्यान दें कि dynamicकेवल LINQ-to-Objects (ORMs के लिए अभिव्यक्ति-पेड़ आदि) पर लागू होता है वास्तव में dynamicप्रश्नों का प्रतिनिधित्व नहीं कर सकता - MemberExpressionइसका समर्थन नहीं करता है। लेकिन यहाँ इसे LINQ-to-Objects के साथ करने का एक तरीका है। ध्यान दें कि पसंद Hashtableलॉकिंग शब्दार्थ के कारण है:

using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Runtime.CompilerServices;
static class Program
{
    private static class AccessorCache
    {
        private static readonly Hashtable accessors = new Hashtable();

        private static readonly Hashtable callSites = new Hashtable();

        private static CallSite<Func<CallSite, object, object>> GetCallSiteLocked(
            string name) 
        {
            var callSite = (CallSite<Func<CallSite, object, object>>)callSites[name];
            if(callSite == null)
            {
                callSites[name] = callSite = CallSite<Func<CallSite, object, object>>
                    .Create(Binder.GetMember(
                                CSharpBinderFlags.None, 
                                name, 
                                typeof(AccessorCache),
                                new CSharpArgumentInfo[] { 
                                    CSharpArgumentInfo.Create(
                                        CSharpArgumentInfoFlags.None, 
                                        null) 
                                }));
            }
            return callSite;
        }

        internal static Func<dynamic,object> GetAccessor(string name)
        {
            Func<dynamic, object> accessor = (Func<dynamic, object>)accessors[name];
            if (accessor == null)
            {
                lock (accessors )
                {
                    accessor = (Func<dynamic, object>)accessors[name];
                    if (accessor == null)
                    {
                        if(name.IndexOf('.') >= 0) {
                            string[] props = name.Split('.');
                            CallSite<Func<CallSite, object, object>>[] arr 
                                = Array.ConvertAll(props, GetCallSiteLocked);
                            accessor = target =>
                            {
                                object val = (object)target;
                                for (int i = 0; i < arr.Length; i++)
                                {
                                    var cs = arr[i];
                                    val = cs.Target(cs, val);
                                }
                                return val;
                            };
                        } else {
                            var callSite = GetCallSiteLocked(name);
                            accessor = target =>
                            {
                                return callSite.Target(callSite, (object)target);
                            };
                        }
                        accessors[name] = accessor;
                    }
                }
            }
            return accessor;
        }
    }

    public static IOrderedEnumerable<dynamic> OrderBy(
        this IEnumerable<dynamic> source, 
        string property)
    {
        return Enumerable.OrderBy<dynamic, object>(
            source, 
            AccessorCache.GetAccessor(property), 
            Comparer<object>.Default);
    }

    public static IOrderedEnumerable<dynamic> OrderByDescending(
        this IEnumerable<dynamic> source, 
        string property)
    {
        return Enumerable.OrderByDescending<dynamic, object>(
            source, 
            AccessorCache.GetAccessor(property), 
            Comparer<object>.Default);
    }

    public static IOrderedEnumerable<dynamic> ThenBy(
        this IOrderedEnumerable<dynamic> source, 
        string property)
    {
        return Enumerable.ThenBy<dynamic, object>(
            source, 
            AccessorCache.GetAccessor(property), 
            Comparer<object>.Default);
    }

    public static IOrderedEnumerable<dynamic> ThenByDescending(
        this IOrderedEnumerable<dynamic> source, 
        string property)
    {
        return Enumerable.ThenByDescending<dynamic, object>(
            source, 
            AccessorCache.GetAccessor(property), 
            Comparer<object>.Default);
    }

    static void Main()
    {
        dynamic a = new ExpandoObject(), 
                b = new ExpandoObject(), 
                c = new ExpandoObject();
        a.X = "abc";
        b.X = "ghi";
        c.X = "def";
        dynamic[] data = new[] { 
            new { Y = a },
            new { Y = b }, 
            new { Y = c } 
        };

        var ordered = data.OrderByDescending("Y.X").ToArray();
        foreach (var obj in ordered)
        {
            Console.WriteLine(obj.Y.X);
        }
    }
}

109
बेस्ट लानत का टुकड़ा मैंने देखा है :) बस मेरी परियोजना में एक लाख समस्याओं का हल किया :)
साजिदनिज़ामी

4
@ क्या - आपको शुरुआत करने की आवश्यकता है IQueryable<T>, इसलिए यदि आपके पास कुछ ऐसा है List<T>(जो है IEnumerable<T>) तो आपको उपयोग करने की आवश्यकता हो सकती है AsQueryable()- उदाहरण के लिएvar sorted = someList.AsQueryable().OrderBy("Foo.Bar");
मार्क ग्रेवेल

7
क्या आपने इसे देखा है ... यह कुछ लोगों की मदद कर सकता है ... stackoverflow.com/questions/557819/… इसका अधिक जोरदार टाइप किया हुआ समाधान है।
एन्थोनीव

28
@MGOwen आप कोड की प्रकृति को गलत समझते हैं। ४० लाइनें वही हैं चाहे वह ४० लाइनें हों जो आप अपने प्रोजेक्ट में कहीं डालते हैं, या यदि वे लाइनें किसी बाहरी लाइब्रेरी में (पूर्व-संकलित, या स्रोत के रूप में) आती हैं। यह बहुत आश्चर्यजनक होता अगर मैं जुड़ा होता, अक्टूबर '08 में एक पुस्तकालय के लिए एक नगीट पर एक पुस्तकालय जो दिसम्बर '11 से अस्तित्व में है (कम से कम क्योंकि नगेट तब मौजूद नहीं था), लेकिन मौलिक "यह क्या कर रहा है" है वही। इसके अलावा, आप "वास्तविक समाधान" वाक्यांश का उपयोग करते हैं, हालांकि प्रत्येक कोडिंग प्रश्न के लिए कुछ अच्छी तरह से परिभाषित एकल मार्ग है: वहाँ नहीं है।
मार्क Gravell

5
@MGOwen btw, बाहरी परिवाद कोड की 2296 पंक्तियाँ हैं (असेंबलीइन्फो शामिल नहीं हैं।); जो थोड़े यहाँ 40 लाइनों सुंदर उचित देखने में आता है
मार्क Gravell

231

बिना किसी जटिलता के बहुत आसान:

  1. using System.Linq.Dynamic;शीर्ष पर जोड़ें ।
  2. उपयोग vehicles = vehicles.AsQueryable().OrderBy("Make ASC, Year DESC").ToList();

11
और आपको कहां से मिला System.Linq.Dynamic?
विदाई

1
MongoDB के साथ ही linq का उपयोग करते समय भी काम करता है।
soupy1976

32
2008 में स्वीकृत उत्तर सही उत्तर हो सकता है, लेकिन वर्तमान में यह सबसे आसान, सबसे सही उत्तर है।
एलएल मोजो

1
यह वास्तव में अच्छा और सरल हैंडलिंग है, इतनी जटिलता आंतरिक रूप से, इसे प्यार करती थी
मृणाल कांबोज

5
"भविष्य" में लोगों के लिए, यदि आप डॉटनेट
Rafael Merlin

78

मुझे जवाब मिल गया। मैं .AsQueryable<>()अपनी सूची को IQueryable में बदलने के लिए एक्सटेंशन विधि का उपयोग कर सकता हूं, फिर इसके खिलाफ डायनेमिक ऑर्डर चला सकता हूं।


52
कृपया हममें से बाकी लोगों के लिए एक उदाहरण प्रदान करें।
MGOwen

54

बस इस सवाल पर ठोकर खाई।

ऊपर से मार्क के ApplyOrder कार्यान्वयन का उपयोग करते हुए, मैंने एक एक्सटेंशन पद्धति को एक साथ थप्पड़ मारा जो SQL- जैसे स्ट्रिंग्स को संभालती है जैसे:

list.OrderBy("MyProperty DESC, MyOtherProperty ASC");

विवरण यहाँ पाया जा सकता है: http://aonnull.blogspot.com/2010/08/dynamic-sql-like-linq-orderby-extension.html


1
महान सामान, संपत्ति के नाम के मामले को असंवेदनशील बनाने के लिए सिर्फ एक संशोधन जोड़ें: PropertyInfo pi = type.GetProperty (Prop, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase)
मृणाल कंबोज

43

मुझे लगता है कि जिस भी संपत्ति को आप छाँटना चाहते हैं उसे पाने के लिए प्रतिबिंब का उपयोग करना काम करेगा:

IEnumerable<T> myEnumerables
var query=from enumerable in myenumerables
          where some criteria
          orderby GetPropertyValue(enumerable,"SomeProperty")
          select enumerable

private static object GetPropertyValue(object obj, string property)
{
    System.Reflection.PropertyInfo propertyInfo=obj.GetType().GetProperty(property);
    return propertyInfo.GetValue(obj, null);
}

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


क्या यह भी काम करता है? ऑर्डरबी को एक मूल्य नहीं बल्कि एक चयनकर्ता लांबा / डेलीगेट (फंक <TSource, TKey> keySelector) चाहिए
डेवी लैंडमैन

2
मैंने इसे पोस्ट करने से पहले इस उदाहरण की कोशिश की, और हां, यह काम करता है।
Kjetil Watnedal

3
+1 यह वही है जो मैं देख रहा था! यह साधारण पृष्ठ सॉर्टिंग समस्याओं के लिए बहुत अच्छा काम करेगा।
एंड्रयू सिएमर

यह मेरे लिए काम नहीं किया। क्या मैं कुछ भूल रहा हूँ? "SomeProperty" क्या होना चाहिए। मैंने प्रॉपर्टी के नाम के साथ-साथ प्रॉपर्टी का नाम देने की कोशिश की ।GetType ()। मेरे पास IQueryable <> है न कि IEnumerable <>
SO उपयोगकर्ता

2
@Alex Shkor: कैसे आप सभी तत्वों को देखे बिना तत्वों को क्रमबद्ध करने वाले हैं? हालांकि, अन्य उत्तरों में बेहतर समाधान हैं।
Kjetil Watnedal

19

बस दूसरों ने जो कहा है उस पर निर्माण करना। मैंने पाया कि निम्नलिखित काफी अच्छी तरह से काम करता है।

public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> input, string queryString)
{
    if (string.IsNullOrEmpty(queryString))
        return input;

    int i = 0;
    foreach (string propname in queryString.Split(','))
    {
        var subContent = propname.Split('|');
        if (Convert.ToInt32(subContent[1].Trim()) == 0)
        {
            if (i == 0)
                input = input.OrderBy(x => GetPropertyValue(x, subContent[0].Trim()));
            else
                input = ((IOrderedEnumerable<T>)input).ThenBy(x => GetPropertyValue(x, subContent[0].Trim()));
        }
        else
        {
            if (i == 0)
                input = input.OrderByDescending(x => GetPropertyValue(x, subContent[0].Trim()));
            else
                input = ((IOrderedEnumerable<T>)input).ThenByDescending(x => GetPropertyValue(x, subContent[0].Trim()));
        }
        i++;
    }

    return input;
}

12

मैंने इस प्रश्न को लाइनक के कई क्रमबद्ध खंडों की तलाश में रोक दिया है और शायद लेखक की तलाश थी

यहाँ है कि कैसे करना है:

var query = pets.OrderBy(pet => pet.Name).ThenByDescending(pet => pet.Age);    

5
+1 ने स्पष्टीकरण की कमी के कारण डाउन-वोट रद्द कर दिया। मुझे यह भी लगता है कि लेखक को कई ऑर्डर-बाय में दिलचस्पी रही होगी। यहां तक कि अगर गतिशील था महत्वपूर्ण शब्द, नीचे वोट का कोई कारण नहीं।
जेसन क्लेबन

11

मैं ऐसा करने की कोशिश कर रहा था, लेकिन Kjetil Watnedal के समाधान के साथ समस्या है क्योंकि मैं इनलाइन लाइनिक सिंटैक्स का उपयोग नहीं करता हूं - मैं पद्धति-शैली सिंटैक्स पसंद करता हूं। मेरी विशिष्ट समस्या एक कस्टम का उपयोग करके गतिशील छंटाई करने की कोशिश में थीIComparer

मेरा समाधान इस तरह समाप्त हुआ:

इस तरह एक IQueryable क्वेरी को देखते हुए:

List<DATA__Security__Team> teams = TeamManager.GetTeams();
var query = teams.Where(team => team.ID < 10).AsQueryable();

और एक रन-टाइम सॉर्ट फ़ील्ड तर्क दिया:

string SortField; // Set at run-time to "Name"

डायनेमिक ऑर्डरबी ऐसा दिखता है:

query = query.OrderBy(item => item.GetReflectedPropertyValue(SortField));

और वह GetReflectedPropertyValue () नामक एक छोटी सहायक विधि का उपयोग कर रहा है:

public static string GetReflectedPropertyValue(this object subject, string field)
{
    object reflectedValue = subject.GetType().GetProperty(field).GetValue(subject, null);
    return reflectedValue != null ? reflectedValue.ToString() : "";
}

एक आखिरी बात - मैंने उल्लेख किया कि मैं OrderByकस्टम का उपयोग IComparerकरना चाहता था - क्योंकि मैं प्राकृतिक छंटाई करना चाहता था ।

ऐसा करने के लिए, मैं सिर्फ इसमें परिवर्तन करता हूं OrderBy:

query = query.OrderBy(item => item.GetReflectedPropertyValue(SortField), new NaturalSortComparer<string>());

कोड के लिए इस पोस्ट को देखें NaturalSortComparer()


5

गतिशील का उपयोग करें linq

बस जोड़ दो using System.Linq.Dynamic;

और अपने सभी कॉलमों को क्रमबद्ध करने के लिए इसका उपयोग इस तरह करें:

string sortTypeStr = "ASC"; // or DESC
string SortColumnName = "Age"; // Your column name
query = query.OrderBy($"{SortColumnName} {sortTypeStr}");

4

आप इसे जोड़ सकते हैं:

public static IEnumerable<T> OrderBy( this IEnumerable<T> input, string queryString) {
    //parse the string into property names
    //Use reflection to get and sort by properties
    //something like

    foreach( string propname in queryString.Split(','))
        input.OrderBy( x => GetPropertyValue( x, propname ) );

    // I used Kjetil Watnedal's reflection example
}

GetPropertyValueसमारोह से है Kjetil Watnedal के जवाब

मुद्दा यह होगा कि क्यों? ऐसा कोई भी संकलन संकलन समय के बजाय रन-टाइम पर अपवादों को फेंक देगा (जैसे D2VIANT का उत्तर)।

यदि आप Linq को Sql के साथ काम कर रहे हैं और ऑर्डरबी एक एक्सप्रेशन ट्री है तो इसे SQL में निष्पादन के लिए वैसे भी परिवर्तित कर दिया जाएगा।


GetPropertyValue mehotod को सभी तत्वों के लिए निष्पादित किया जाएगा, यह बुरा समाधान है।
एलेक्स शकोर

2
OrderByपिछले आदेश को बनाए न रखें !!
अमीर इस्माइल

4

यहाँ कुछ और है जो मुझे दिलचस्प लगा। यदि आपका स्रोत डेटाटेबल है, तो आप डायनेमिक लाइनक का उपयोग किए बिना डायनेमिक सॉर्टिंग का उपयोग कर सकते हैं

DataTable orders = dataSet.Tables["SalesOrderHeader"];
EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         orderby order.Field<DateTime>("OrderDate")
                                         select order;
DataView view = query.AsDataView();
bindingSource1.DataSource = view;

संदर्भ: http://msdn.microsoft.com/en-us/library/bb669083.aspx (DataSetExtensions का उपयोग करके)

इसे डेटा दृश्य में परिवर्तित करके इसे करने का एक और तरीका है:

DataTable contacts = dataSet.Tables["Contact"];    
DataView view = contacts.AsDataView();    
view.Sort = "LastName desc, FirstName asc";    
bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();

4

Maarten के लिए धन्यवाद ( LINQ LINQ में PropertyInfo ऑब्जेक्ट का उपयोग कर एक संग्रह ) मुझे यह समाधान मिला:

myList.OrderByDescending(x => myPropertyInfo.GetValue(x, null)).ToList();

मेरे मामले में मैं एक "ColumnHeaderMouseClick" (WindowsForm) पर काम कर रहा था, इसलिए बस विशिष्ट कॉलम को दबाया गया और उसके संवाददाता को पता चला संपत्ति:

foreach (PropertyInfo column in (new Process()).GetType().GetProperties())
{
    if (column.Name == dgvProcessList.Columns[e.ColumnIndex].Name)
    {}
}

या

PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First();

(अपने कॉलम का नाम वस्तु गुणों से मेल खाते हुए अवश्य रखें)

चियर्स


4

बहुत खोज के बाद इसने मेरे लिए काम किया:

public static IEnumerable<TEntity> OrderBy<TEntity>(this IEnumerable<TEntity> source, 
                                                    string orderByProperty, bool desc)
{
    string command = desc ? "OrderByDescending" : "OrderBy";
    var type = typeof(TEntity);
    var property = type.GetProperty(orderByProperty);
    var parameter = Expression.Parameter(type, "p");
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
    var orderByExpression = Expression.Lambda(propertyAccess, parameter);
    var resultExpression = Expression.Call(typeof(Queryable), command, 
                                           new[] { type, property.PropertyType },
                                           source.AsQueryable().Expression, 
                                           Expression.Quote(orderByExpression));
    return source.AsQueryable().Provider.CreateQuery<TEntity>(resultExpression);
}


3

एक वैकल्पिक समाधान निम्न वर्ग / इंटरफ़ेस का उपयोग करता है। यह वास्तव में गतिशील नहीं है, लेकिन यह काम करता है।

public interface IID
{
    int ID
    {
        get; set;
    }
}

public static class Utils
{
    public static int GetID<T>(ObjectQuery<T> items) where T:EntityObject, IID
    {
        if (items.Count() == 0) return 1;
        return items.OrderByDescending(u => u.ID).FirstOrDefault().ID + 1;
    }
}

2

यह उत्तर उन टिप्पणियों की प्रतिक्रिया है, जो @ जोहान शीहान द्वारा प्रदान किए गए समाधान के लिए एक उदाहरण की आवश्यकता है - रनस्कोप

कृपया हममें से बाकी लोगों के लिए एक उदाहरण प्रदान करें।

डीएएल (डाटा एक्सेस लेयर) में,

IEnumerable संस्करण:

  public  IEnumerable<Order> GetOrders()
    {
      // i use Dapper to return IEnumerable<T> using Query<T>
      //.. do stuff
      return  orders  // IEnumerable<Order>
  }

IQueryable संस्करण

  public IQueryable<Order> GetOrdersAsQuerable()
    {
        IEnumerable<Order> qry= GetOrders();
        //use the built-in extension method  AsQueryable in  System.Linq namespace
        return qry.AsQueryable();            
    }

अब आप बाइंड करने के लिए IQueryable संस्करण का उपयोग कर सकते हैं, उदाहरण के लिए Asp.net में GridView और सॉर्ट करने के लिए लाभ (आप IEnumerable संस्करण का उपयोग करके सॉर्ट नहीं कर सकते हैं)

मैंने Dapper को ORM के रूप में उपयोग किया और IQueryable संस्करण का निर्माण किया और Asp.net में GridView में इतना आसान छँटाई का उपयोग किया।


2

पहले डायनेमिक टूल इंस्टॉल करें -> NuGet पैकेज मैनेजर -> पैकेज मैनेजर कंसोल

install-package System.Linq.Dynamic

जोड़े नामस्थान using System.Linq.Dynamic;

अब आप उपयोग कर सकते हैं OrderBy("Name, Age DESC")


मैं इसे आंतरिक संपत्ति छाँटने के साथ कैसे उपयोग कर सकता हूं - जैसे ऑर्डरबाय ("ब्रांच.ब्रांचनाम", "अवरोही")
devC

यह मेरे लिए काम करता है। शायद इसलिए कि सवाल 10 साल पुराना है, और यह आसान तरीका केवल बाद में आया।
कोसरजेलीफ़िश

1

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

        public List<Book> Books(string orderField, bool desc, int skip, int take)
{
    var propertyInfo = typeof(Book).GetProperty(orderField);

    return _context.Books
        .Where(...)
        .OrderBy(p => !desc ? propertyInfo.GetValue(p, null) : 0)
        .ThenByDescending(p => desc ? propertyInfo.GetValue(p, null) : 0)
        .Skip(skip)
        .Take(take)
        .ToList();
}

कुछ साल बाद और मैं इस पर ठोकर खाता हूं; यह मेरे लिए, एक सपने की तरह काम किया। मेरे पास 1 से 3 गुणों पर गतिशील छंटनी है, और यह एक सपने की तरह काम करता है। लागू करने में आसान और परेशानी मुक्त।
बाज़िंगा

0

सूची को IEnumerable या Iquerable में बदलें, System.LINQ.Dynamic namespace का उपयोग करके जोड़ें, फिर u आप अल्पविराम से अलग किए गए संपत्ति के नामों को OrderBy Method में उल्लेख कर सकते हैं, जो System.LINQ.Dynamic से डिफ़ॉल्ट रूप से आता है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.