জেনেরিক এক্সটেনশন পদ্ধতির মধ্যে আমি স্ট্রিং কলামের নাম ব্যবহার করে আইকিউয়ারেবলে অর্ডারবাই কীভাবে প্রয়োগ করব?


85
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);
}

কারণ অর্ডারবাইয়ের ধরণটি বাছাই করা এক্সপ্রেশন থেকে অনুমান করা হয় না আমাকে রান সময় এটির মতো কিছু নির্দিষ্ট করা দরকার:

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

বা

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

আমি মনে করি না এটি সম্ভব হয়েছে তবে টিসার্টকলাম কেবল রানটাইমের সময় নির্ধারণ করা যেতে পারে।

এই সমস্যা এড়ানোর একটি উপায় আছে কি?


যদি নিশ্চিত না এই আপনি যা খুঁজছেন করছি, কিন্তু কটাক্ষপাত করা। চিয়ার্স
joopintocruz

@JTew আমি কিভাবে তারিখ অনুসারে তারপর clause..say orderby ID দ্বারা একটি দ্বিতীয় অর্ডার বাস্তবায়ন করতে পারে
SRJ

উত্তর:


113

আমরা একটি লিনকিউ থেকে এসকিউএল প্রকল্পে অনুরূপ (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));


4
অবরোহী জন্য, "OrderBy" MethodCallExpression resultExp = Expression.Call (typeof (Queryable), "OrderByDescending" এর "OrderByDescending" মধ্যে পাস পরিবর্তে, ...
গ্যারি ইংরেজি

4
এই মাত্র জরিমানা কাজ, কিন্তু নিম্নলিখিত মাত্র একটি সত্যিই চমৎকার পরিষ্কার কোড উদাহরণস্বরূপ ছিল: stackoverflow.com/questions/41244/dynamic-linq-orderby
BenSwayne

@Aaron পাওয়েল আমি কিভাবে তারিখ অনুসারে তারপর clause..say orderby ID দ্বারা একটি দ্বিতীয় অর্ডার বাস্তবায়ন করতে পারে
SRJ

4
প্যারামিটার কী values?
ফ্র্যাঙ্ক ফাজার্ডো

31

আপনি ডায়নামিক লিনকও ব্যবহার করতে পারেন

এখানে তথ্য 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");

ধন্যবাদ, আমি ফিল হ্যাকের সাইটে একটি নমুনায় লিঙ্ক.ডায়নামিক দেখেছি কিন্তু এটি সম্পর্কে অনিশ্চিত ছিল। আমি সপ্তাহান্তে এই সাথে একটি নাটক করব।
জেটিউ

: একটি বিকল্প Systems.Linq.Dynamic.dll এখান থেকে ডাউনলোড করা যাবে হিসাবে github.com/kahanu/System.Linq.Dynamic
বেগ

12

শিশু সম্পত্তিগুলির জন্য সমর্থন যুক্ত করতে আমি আপনার কার্যগুলি বাড়িয়ে দিয়েছি।

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);

4
আপনি আমার নায়ক !!
সেবাস্তিয়ান গেরেরো

4
স্মার্ট লোকদের পছন্দ করতে হবে
রড জনসন

আমি এই কোডটি চেষ্টা করেছি এবং এটি একটি সন্তানের সাথে কাজ করে তবে একের বেশি নয়, উদাহরণস্বরূপ এটি x.String এবং x.Object.String এ বাছাই করে কাজ করে তবে x.Object.Object.String এ বাছাইয়ের সাথে নয়।
রবার্ট রেট

8

আমি অর্ডারবাইয়ের জন্য আপনার ধারণাটি এক্সটেনশন পদ্ধতির জন্য ব্যবহার করেছি। তবে "অনেকের কাছে অনেকের" ক্ষেত্রে আমি ত্রুটি পাচ্ছি। উদাহরণস্বরূপ আপনার টেবিল সাইট, গ্রাহক এবং গ্রাহক_সাইট রয়েছে। প্রদত্ত সাইটের জন্য আমি গ্রাহকের নাম অনুসারে বাছাই করতে চাই এবং অর্ডারবাই এক্সটেনশনে (যখন আমি "সাইট কাস্টমার" পাস করি যেখানে গ্রাহক নেভিগেশন সম্পত্তি) আমি লাইনে ত্রুটি পাই: সম্পত্তিAccess = এক্সপ্রেশন.মেকমেবারঅ্যাক্সেস (প্রপার্টিঅ্যাক্সেস, সম্পত্তি);

এটি আমি ব্যবহার করি (কিছু বর্ধনের সাথে :-)):

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;
}

শ্রদ্ধা

স্লোবোডান


6

মনে হচ্ছে যে এই পথ এটা করতে, এখন যে তা যাচাই করা:

// ***** 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 *****

4
অভিহিত, 34 সেকেন্ড পিছনে! : পি
অ্যারন পাওয়েল

3

আপনি যদি তখন "সিস্টেম.লিনক.ডায়নামিক" প্যাকেজ যুক্ত করতে সক্ষম হন তবে কোনও জটিলতা ছাড়াই খুব সহজ,

নুগেট প্যাকেজ ম্যানেজারের 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

আমি এই কোডটি কিছুটা ঠিক করেছি: 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;
}

0

@ ডেভি ল্যান্ডম্যানের উত্তর থেকে আমার অভিযোজনটি এখানে রয়েছে (আমি একটি এক্সটেনশন পদ্ধতি চাইছিলাম) এবং আমি কিছুটা সরলীকৃত করেছি।

public static IQueryable<T> SortBy<T>(this IQueryable<T> source, 
                                      String propertyName, 
                                      WebControls.SortDirection direction)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (String.IsNullOrEmpty(propertyName)) return source;

        // Create a parameter to pass into the Lambda expression
        //(Entity => Entity.OrderByField).
        var parameter = Expression.Parameter(typeof(T), "Entity");

        //  create the selector part, but support child properties (it works without . too)
        String[] childProperties = propertyName.Split('.');
        MemberExpression property = Expression.Property(parameter, childProperties[0]);
        for (int i = 1; i < childProperties.Length; i++)
        {
            property = Expression.Property(property, childProperties[i]);
        }

        LambdaExpression selector = Expression.Lambda(property, parameter);

        string methodName = (direction > 0) ? "OrderByDescending" : "OrderBy";

        MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName,
                                        new Type[] { source.ElementType, property.Type },
                                        source.Expression, Expression.Quote(selector));

        return source.Provider.CreateQuery<T>(resultExp);
    }

এটি এর মতো ব্যবহার করা যেতে পারে:

gridview1.DataSource = DbContext.TB_CARS.SortBy("model", SortDirection.Descending);
//OR
gridview1.DataSource = DbContext.TB_CARS.SortBy("owner.first_name", 0);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.