【问题标题】:Using given properties as strings使用给定的属性作为字符串
【发布时间】:2012-09-06 16:51:39
【问题描述】:

我想使用一种单一的通用方法来检索表示 lambda 表达式中属性的给定字符串的有序列表。

我知道以前有人要求过这个,但它对我不起作用。我试过了,它抛出了错误:

db.Books.OrderByDescending(x => x.GetType().GetProperty("Discount").GetValue(x,null))
        .Take(3);

我现在正在使用这个:

public IQueryable<Book> GetCheapestBooks()
{
    return db.Books.OrderBy(x => x.Discount)
                   .Take(3);
}

【问题讨论】:

  • 第一个示例抛出的错误是什么?在您的第二个示例中,results 等于什么?
  • 我收到此错误:无法按类型“System.Object”订购
  • 我尝试了这些建议,除了 .tolist() 想法(由 L.B 提出)之外,没有其他建议有效,但它有它的缺陷,所以我不确定我是否应该使用它而不是创建一些更具体的方法。
  • p.s:顺便说一下,我的意思是简短的建议
  • 好吧,我猜这是语法问题,这是一个有效的方法:results = (from book in db.Books orderby ("Discount") select book).Take(3);

标签: c# .net sql linq sql-order-by


【解决方案1】:

也许这就是你要找的东西:

Dynamic Linq

有了这个,你可以编写如下查询:

var result = db.Books.OrderBy( "Discount" ).Take( 3 );

【讨论】:

    【解决方案2】:

    简单的控制台应用程序。

    class A
            {
                public int prop1 { get; set; }
                public int prop2 { get; set; }
            }
    
        class Program
        {
            static IEnumerable<T> GenericOrderByDescending<T>(IEnumerable<T> arg, string property, int take)
            {
                return arg.OrderByDescending(x => x.GetType().GetProperty(property).GetValue(x, null)).Take(take);
            }
    
            static void Main(string[] args)
            {           
                IEnumerable<A> arr = new List<A>()
                                         {
                                             new A(){ prop1 = 1, prop2 = 2},
                                             new A(){prop1 = 2,prop2 =2},
                                             new A(){prop1 = 3,prop2 =2},
                                             new A(){prop1 = 441,prop2 =2},
                                             new A(){prop1 = 2,prop2 =2}
                                         };
    
                foreach(var a1 in GenericOrderByDescending<A>(arr, "prop1", 3))
                {
                    Console.WriteLine(a1.prop1);
                }
            }
        }
    

    您可以将您的db.Boks.AsEnumerable() 作为GenericOrderByDescending&lt;T&gt;() 方法的参数传递。您应该键入 db.Boks 项目的类型,而不是 T。我的示例对 A 类的实例数组进行排序,我没有错误,它工作正常。我没听错吗?

    【讨论】:

      【解决方案3】:

      你可以试试这段代码

      public IQueryable<Book> GetCheapestBooks()
      {
          db.Books.OrderBy(x => x.Discount).Take(3).AsQueryable<Book>();
      }
      

      【讨论】:

        【解决方案4】:

        您可以创建一个扩展方法来创建属性表达式:

        private static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
        {
            PropertyInfo prop = typeof(T).GetProperty(propertyName);
            ParameterExpression paramExpr = Expression.Parameter(typeof(T), "obj");
            MemberExpression propExpr = Expression.Property(paramExpr, prop);
        
            Type funcType = typeof(Func<,>).MakeGenericType(typeof(T), prop.PropertyType);
            Type keySelectorType = typeof(Expression<>).MakeGenericType(funcType);
            LambdaExpression keySelector = Expression.Lambda(funcType, propExpr, paramExpr);
        
            MethodInfo orderByMethod = typeof(Queryable).GetMethods().Single(m => m.Name == "OrderBy" && m.GetParameters().Length == 2).MakeGenericMethod(typeof(T), prop.PropertyType);
            return (IOrderedQueryable<T>) orderByMethod.Invoke(null, new object[] { source, keySelector });
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-07-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-26
          • 2015-01-21
          • 2023-03-16
          相关资源
          最近更新 更多