【问题标题】:How to query column name compare with a string?如何查询列名与字符串比较?
【发布时间】:2016-04-04 09:55:36
【问题描述】:

我想根据作为字符串的列名对我的列进行排序,但不幸的是我无法做到这一点,因为OrderByDescending 比较了其他内容,但我正在发送一个字符串。

public List<DOlead> sortLead(DOuser user, string Item)
    {
        List<DOlead> ObjLead = new List<DOlead>();
        ObjLead = _Context.leads.Where(x => x.is_converted == false).OrderByDescending(Item).ToList();
        return ObjLead;
    }

请帮帮我?

【问题讨论】:

  • 应该是OrderByDescending(x =&gt; x.columnName)
  • 你有什么错误吗?
  • 您可能需要查看动态 LINQ 查询库 - weblogs.asp.net/scottgu/…
  • 基本上我想在列名的基础上进行排序,该列名将出现在一个字符串中。所以 OrderByDescending(x => x.columnName == Item) 不能工作。
  • 比较别的请解释一下。

标签: c# asp.net sql-server asp.net-mvc-4 linq-to-entities


【解决方案1】:

从 Stack ,我猜你可以使用反射:

from x in db.TableName
    where (x.GetType().GetProperty(stringCOLUMN_1_or2).GetValue(x, null)) == " 8"
select x;

不确定是否有任何简单的 Linqish 方法可以做到这一点......

Assuming dynamic Linq will work it would just be:

from x in objets
.Where(stringCOLUMN_1_or2  + " = ' " + 8 + "'")
select x

这里有更多关于使用 SQL 的动态 Linq 的信息: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

【讨论】:

  • 我使用了 x.GetType().GetProperty(Item)。它给出了异常“LINQ to Entities 无法识别方法 'System.Reflection.PropertyInfo GetProperty(System.String)' 方法,并且该方法无法转换为存储表达式。”
【解决方案2】:

使用反射

public List<DOlead> sortLead(DOuser user, string Item)
{    
    var propertyInfo = typeof(DOlead).GetProperty(Item);    
    List<DOlead> ObjLead = new List<DOlead>();
    ObjLead = _Context.leads.Where(x => x.is_converted == false).OrderByDescending(x => propertyInfo.GetValue(x, null)).ToList();
    return ObjLead;
}

编辑 在得到 SO 的评论后,经过一番研究,我遇到了this answer 并决定为用户修改它。

您必须先创建 lambda 表达式,然后将其传递给 order by 子句。

创建 lambda 表达式。

public static class QueryableHelper
{
    public static IQueryable<TModel> OrderBy<TModel>(this IQueryable<TModel> q, string name)
    {
        Type entityType = typeof(TModel);
        PropertyInfo p = entityType.GetProperty(name);
        MethodInfo m = typeof(QueryableHelper).GetMethod("OrderByProperty").MakeGenericMethod(entityType, p.PropertyType);
        return(IQueryable<TModel>) m.Invoke(null, new object[] { q, p });
    }

    public static IQueryable<TModel> OrderByDescending<TModel>(this IQueryable<TModel> q, string name)
    {
        Type entityType = typeof(TModel);
        PropertyInfo p = entityType.GetProperty(name);
        MethodInfo m = typeof(QueryableHelper).GetMethod("OrderByPropertyDescending").MakeGenericMethod(entityType, p.PropertyType);
        return (IQueryable<TModel>)m.Invoke(null, new object[] { q, p });
    }

    public static IQueryable<TModel> OrderByPropertyDescending<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p)
    {
        ParameterExpression pe = Expression.Parameter(typeof(TModel));
        Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object));
        return q.OrderByDescending(Expression.Lambda<Func<TModel, TRet>>(se, pe));
    }

    public static IQueryable<TModel> OrderByProperty<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p)
    {
        ParameterExpression pe = Expression.Parameter(typeof(TModel));
        Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object));
        return q.OrderBy(Expression.Lambda<Func<TModel, TRet>>(se, pe));
    }
}

你修改的方法

public List<DOlead> sortLead(DOuser user, string Item)
    {      
        List<DOlead> ObjLead = new List<DOlead>();
        ObjLead = _Context.leads.Where(x => x.is_converted == false).OrderByDescending(Item).ToList();
        return ObjLead;
    }

【讨论】:

  • 感谢 Imad Bhai!但它显示异常“LINQ to Entities 无法识别方法 'System.Object GetValue(System.Object, System.Object[])' 方法,并且此方法无法转换为存储表达式。”
  • 很棒的扩展方法。然而,一个建议是让它们返回 IOrderedQueryable 而不是 IQueryable,就像实际的 OrderBy 一样。这允许与 ThenBy 等链接。
【解决方案3】:

你应该使用 Expression builder 来实现这个带有字符串属性的简单示例:

public class OrderByData
    {
        public string PropertyName { get; set; }
    }
    public static class ExpressionBuilder
    {
        public static Expression<Func<T, string>> GetExpression<T>(OrderByData filter)
        {

            ParameterExpression param = Expression.Parameter(typeof(T), "t");
            Expression exp = GetExpression<T>(param, filter);
            return Expression.Lambda<Func<T, string>>(exp, param);
        }

        private static Expression GetExpression<T>(ParameterExpression param, OrderByData filter)
        {
            MemberExpression member = Expression.Property(param, filter.PropertyName);
            return member;
        }
    }

然后像这样调用:

    public List<DOlead> sortLead(DOuser user, string Item)
        {
            List<DOlead> ObjLead = new List<DOlead>();
 new OrderByData { PropertyName = Item };
            var deleg = ExpressionBuilder.GetExpression<lead>(filter).Compile();
            ObjLead = _Context.leads.Where(x => x.is_converted == false).OrderByDescending(deleg).ToList();
            return ObjLead;
        }

您也可以扩展以使用其他类型,而不仅仅是字符串。

【讨论】:

    【解决方案4】:

    您需要将委托传递给OrderByDescending 方法。 由于您只有属性名称,因此您需要动态访问该属性,您可以使用动态表达式来执行此操作:

    public List<DOlead> sortLead(DOuser user, string Item)
        {
            List<DOlead> ObjLead = new List<DOlead>();
            ObjLead = _Context.leads.Where(x => x.is_converted == false).OrderByDescending((d) =>
                     Expression.Lambda(Expression.Property(Expression.Constant(d), Item)).Compile()()).ToList();
            return ObjLead;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多