सवाल मैं जेनेरिक एक्सटेंशन विधि के भीतर स्ट्रिंग कॉलम नाम का उपयोग करके IQueryable पर ऑर्डरबी को कैसे लागू करूं?


public static IQueryable<TResult> ApplySortFilter<T, TResult>(this IQueryable<T> query, string columnName)
  where T : EntityObject
{
  var param = Expression.Parameter(typeof(T), "o");
  var body = Expression.PropertyOrField(param,columnName);

  var sortExpression = Expression.Lambda(body, param);
  return query.OrderBy(sortExpression);
}

क्योंकि ऑर्डरबी के प्रकार को sortExpression से अनुमानित नहीं किया गया है, इसलिए मुझे इसे रन टाइम पर कुछ निर्दिष्ट करने की आवश्यकता है:

var sortExpression = Expression.Lambda<T, TSortColumn>(body, param);

या

return query.OrderBy<T, TSortColumn>(sortExpression);

मुझे नहीं लगता कि यह संभव है हालांकि टीएसोर्ट कॉलम केवल रनटाइम के दौरान निर्धारित किया जा सकता है।

क्या इसके चारों ओर एक रास्ता है?


76
2017-11-21 01:15


मूल


अगर यकीन नहीं इस आप क्या खोज रहे हैं, लेकिन एक नज़र डालें। चियर्स - joaopintocruz
@JTew मैं आज तक ऑर्डरबी आईडी द्वारा क्लॉज द्वारा दूसरे आदेश को कैसे कार्यान्वित कर सकता हूं - SRJ


जवाब:


हमने LINQ से SQL प्रोजेक्ट में कुछ समान (100% समान नहीं, लेकिन समान) किया था। यहां कोड है:

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values) {
    var type = typeof(T);
    var property = type.GetProperty(ordering);
    var parameter = Expression.Parameter(type, "p");
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
    var orderByExp = Expression.Lambda(propertyAccess, parameter);
    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderBy", new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
    return source.Provider.CreateQuery<T>(resultExp);
}

हमने वास्तव में एक सामान्य का उपयोग नहीं किया था, हमारे पास एक ज्ञात वर्ग था, लेकिन इसे सामान्य पर काम करना चाहिए (मैंने जेनेरिक प्लेसहोल्डर रखा है जहां यह होना चाहिए)।

संपादित करें: अवरोही क्रम के लिए, पास करें OrderByDescending "ऑर्डरबी" के बजाय:

MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderByDescending", new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));

102
2017-11-21 02:01



हे कोई प्रॉब नहीं, मैं खुद को किसी भी तरह का जवाब सौंप नहीं सकता :) - JTew
अवरोही क्रम के लिए, "ऑर्डरबी" के बजाय "ऑर्डरबैडसेकिंग" में पास करें विधिकॉलएक्सप्रेस परिणाम EXX = अभिव्यक्ति। कॉल (टाइप करें (क्वेरी करने योग्य), "ऑर्डरबैडसेकिंग", ... - Garry English
यह ठीक काम करता था, लेकिन निम्नलिखित सिर्फ एक बहुत अच्छा साफ कोड उदाहरण था: stackoverflow.com/questions/41244/dynamic-linq-orderby - BenSwayne
@Aaron Powell मैं आज तक ऑर्डरबी आईडी द्वारा क्लॉज द्वारा दूसरे आदेश को कैसे कार्यान्वित कर सकता हूं - SRJ
पैरामीटर क्या है values के लिये? - Frank Fajardo


आप गतिशील लिंक का भी उपयोग कर सकते हैं

यहां जानकारी http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

सी # यहां डाउनलोड करें http://msdn.microsoft.com/en-us/vcsharp/bb894665.aspx

फिर बस लिंक का उपयोग करें। गतिशील; और आपको स्वचालित रूप से 2 अतिरिक्त एक्सटेंशन विधियां मिलती हैं जिनका उपयोग इस तरह किया जा सकता है

return query.OrderBy("StringColumnName");

27
2018-05-12 16:17



धन्यवाद, मैंने फिलैक की साइट पर एक नमूने में लिंकक। गतिशील देखा था लेकिन इसके बारे में अनिश्चित था। सप्ताहांत में इस के साथ मेरा खेल होगा। - JTew
एक वैकल्पिक के रूप में System.Linq.Dynamic.dll यहां से डाउनलोड किया जा सकता है: github.com/kahanu/System.Linq.Dynamic - Baig


मैंने बाल गुणों के लिए समर्थन जोड़ने के लिए अपने कार्यों को बढ़ाया है।

private static LambdaExpression GenerateSelector<TEntity>(String propertyName, out Type resultType) where TEntity : class
{
    // Create a parameter to pass into the Lambda expression (Entity => Entity.OrderByField).
    var parameter = Expression.Parameter(typeof(TEntity), "Entity");
    //  create the selector part, but support child properties
    PropertyInfo property;
    Expression propertyAccess;
    if (propertyName.Contains('.'))
    {
            // support to be sorted on child fields.
            String[] childProperties = propertyName.Split('.');
            property = typeof(TEntity).GetProperty(childProperties[0]);
            propertyAccess = Expression.MakeMemberAccess(parameter, property);
            for (int i = 1; i < childProperties.Length; i++)
            {
                    property = property.PropertyType.GetProperty(childProperties[i]);
                    propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
            }
    }
    else
    {
            property = typeof(TEntity).GetProperty(propertyName);
            propertyAccess = Expression.MakeMemberAccess(parameter, property);
    }
    resultType = property.PropertyType;                     
    // Create the order by expression.
    return Expression.Lambda(propertyAccess, parameter);
}

private static MethodCallExpression GenerateMethodCall<TEntity>(IQueryable<TEntity> source, string methodName, String fieldName) where TEntity : class
{
    Type type = typeof(TEntity);
    Type selectorResultType;
    LambdaExpression selector = GenerateSelector<TEntity>(fieldName, out selectorResultType);
    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName,
                                    new Type[] { type, selectorResultType },
                                    source.Expression, Expression.Quote(selector));
    return resultExp;
}

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

GenerateMethodCall<TEntity>(source, "OrderByDescending", fieldName);

10
2017-11-21 14:00



आप मेरे हीरो हैं !! - Sebastián Guerrero
स्मार्ट लोगों को प्यार करना होगा - Rod Johnson


मैंने ऑर्डरबी के लिए एक्सटेंशन विधि के लिए आपका विचार इस्तेमाल किया। लेकिन "कई से कई" के मामले में मुझे त्रुटि मिल रही है। उदाहरण के लिए आपके पास टेबल साइट, ग्राहक और ग्राहक_साइट है। दी गई साइट के लिए मैं ग्राहक नाम और ऑर्डरबी एक्सटेंशन में सॉर्ट करना चाहता हूं (जब मैं "साइट.customer" पास करता हूं जहां ग्राहक नेविगेशन प्रॉपर्टी है) मुझे लाइन में त्रुटि मिलती है: propertyAccess = Expression.MakeMemberAccess (propertyAccess, property);

मैं यही उपयोग करता हूं (कुछ संवर्द्धन के साथ :-)):

public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByValues) where TEntity : class
{
  IQueryable<TEntity> returnValue = null;

  string orderPair = orderByValues.Trim().Split(',')[0];
  string command = orderPair.ToUpper().Contains("DESC") ? "OrderByDescending" : "OrderBy";

  var type = typeof(TEntity);
  var parameter = Expression.Parameter(type, "p");

  string propertyName = (orderPair.Split(' ')[0]).Trim();

  System.Reflection.PropertyInfo property;
  MemberExpression propertyAccess;

  if (propertyName.Contains('.'))
  {
    // support to be sorted on child fields. 
    String[] childProperties = propertyName.Split('.');
    property = typeof(TEntity).GetProperty(childProperties[0]);
    propertyAccess = Expression.MakeMemberAccess(parameter, property);

    for (int i = 1; i < childProperties.Length; i++)
    {
      Type t = property.PropertyType;
      if (!t.IsGenericType)
      {
        property = t.GetProperty(childProperties[i]);
      }
      else
      {
        property = t.GetGenericArguments().First().GetProperty(childProperties[i]);
      }

      propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
    }
  }
  else
  {
    property = type.GetProperty(propertyName);
    propertyAccess = Expression.MakeMemberAccess(parameter, property);
  }

  var orderByExpression = Expression.Lambda(propertyAccess, parameter);

  var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },

  source.Expression, Expression.Quote(orderByExpression));

  returnValue = source.Provider.CreateQuery<TEntity>(resultExpression);

  if (orderByValues.Trim().Split(',').Count() > 1)
  {
    // remove first item
    string newSearchForWords = orderByValues.ToString().Remove(0, orderByValues.ToString().IndexOf(',') + 1);
    return source.OrderBy(newSearchForWords);
  }

  return returnValue;
}

सादर

स्लोबोदान


8
2017-11-03 20:56





ऐसा लगता है इस ऐसा करने का तरीका है, अब यह सत्यापित करने के लिए कि:

// ***** OrderBy(company => company) *****
// Create an expression tree that represents the expression
// 'whereCallExpression.OrderBy(company => company)'
MethodCallExpression orderByCallExpression = Expression.Call(
    typeof(Queryable),
    "OrderBy",
    new Type[] { queryableData.ElementType, queryableData.ElementType },
    whereCallExpression,
    Expression.Lambda<Func<string, string>>(pe, new ParameterExpression[] { pe }));
// ***** End OrderBy *****

6
2017-11-21 02:00



दमन, 34 सेकंड पीछे! : पी - Aaron Powell


यदि आप तब "System.Linq.Dynamic" पैकेज जोड़ सकते हैं, किसी भी जटिलता के बिना बहुत आसान है,

NuGet पैकेज मैनेजर से fisrt insatll पैकेज "System.Linq.Dynamic" अपनी जरूरत के रूप में नीचे की कोशिश करो,

उदाहरण के लिए:

public IQueryable<TEntity> GetWithInclude(Expression<Func<TEntity, bool>> predicate,
                    List<string> sortBy, int pageNo, int pageSize = 12, params string[] include)
        {
            try
            {
                var numberOfRecordsToSkip = pageNo * pageSize;
                var dynamic = DbSet.AsQueryable();

                foreach (var s in include)
                {
                    dynamic.Include(s);
                }
                 return dynamic.OrderBy("CreatedDate").Skip(numberOfRecordsToSkip).Take(pageSize);


            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

उम्मीद है कि यह मदद करेगा


2
2018-02-12 17:42





मैंने इस कोड को थोड़ा सा तय किया: https://stackoverflow.com/a/1670085/5852630

यह कोड अनुक्रमिक सॉर्टिंग के साथ काम करता है: पहले "ऑर्डरबी" निष्पादित करें, फिर "फिर से" (नहीं "ऑर्डरबी"!)

public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByValues) where TEntity : class
{
    IQueryable<TEntity> returnValue = null;

    string[] orderPairs = orderByValues.Trim().Split(',');

    Expression resultExpression = source.Expression;

    string strAsc = "OrderBy";
    string strDesc = "OrderByDescending";

    foreach (string orderPair in orderPairs)
    {
        if (string.IsNullOrWhiteSpace(orderPair))
            continue;

        string[] orderPairArr = orderPair.Trim().Split(' ');

        string propertyName = orderPairArr[0].Trim();
        string orderNarrow = orderPairArr.Length > 1 ? orderPairArr[1].Trim() : string.Empty;

        string command = orderNarrow.ToUpper().Contains("DESC") ? strDesc : strAsc;

        Type type = typeof(TEntity);
        ParameterExpression parameter = Expression.Parameter(type, "p");

        System.Reflection.PropertyInfo property;
        Expression propertyAccess;

        if (propertyName.Contains('.'))
        {
            // support to be sorted on child fields. 
            String[] childProperties = propertyName.Split('.');
            property = typeof(TEntity).GetProperty(childProperties[0]);
            propertyAccess = Expression.MakeMemberAccess(parameter, property);

            for (int i = 1; i < childProperties.Length; i++)
            {
                Type t = property.PropertyType;
                if (!t.IsGenericType)
                {
                    property = t.GetProperty(childProperties[i]);
                }
                else
                {
                    property = t.GetGenericArguments().First().GetProperty(childProperties[i]);
                }

                propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
            }
        }
        else
        {
            property = type.GetProperty(propertyName);
            propertyAccess = Expression.MakeMemberAccess(parameter, property);
        }

        if (property.PropertyType == typeof(object))
        {
            propertyAccess = Expression.Call(propertyAccess, "ToString", null);
        }

        LambdaExpression orderByExpression = Expression.Lambda(propertyAccess, parameter);

        resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType == typeof(object) ? typeof(string) : property.PropertyType },
            resultExpression, Expression.Quote(orderByExpression));

        strAsc = "ThenBy";
        strDesc = "ThenByDescending";
    }

    returnValue = source.Provider.CreateQuery<TEntity>(resultExpression);

    return returnValue;
}

1
2018-05-04 13:01