2012-09-19 93 views
1

我有这样的代码:通过编程的LINQ/LAMBDA创建订单

public void CreateOrdering(string field, string direction) 
{ 
    //direction : ASC/DESC 
    var result = context.MyTable 
     .Where(x => x.Code > 5) 
     .OrderBy() 
     .Skip(10) 
     .Take(5) 
     .ToList<MyTable>(); 
} 

我改一下,我有一个方法,这个方法得到的字符串字段名称排序和方向(“ASC”,“降序” )

我想创建一个与领域和方向收到参数的顺序。我必须能够:

  1. 我想在此查询能够做到上升和下降
  2. 设置通过编程的排序字段,这里Code可能是后来Id或其他...
  3. 排序必须在SQL Server端完成不在名单上返回

感谢,

+1

使用动态LINQ http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx –

+0

Linq to XXX。哪一个? –

+1

我想你会想参考这个问题的答案 http://stackoverflow.com/questions/41244/dynamic-linq-orderby – chead23

回答

2

我可能误解了你的问题,但你不能只是做:

升序

.OrderBy(x => x.Property) 

降序

.OrderByDescending(x => x.Property) 

更新

你需要的是Dynamic LINQ。然而,你试图做的事情可能会变得非常复杂。举一个简单的解决方法,你可以这样做:

var result = context.MyTable 
        .Where(x => x.Code > 15); 

if (direction == "ASC") 
{ 
    result = result.OrderBy(field); 
} 
else 
{ 
    result = result.OrderByDescending(field); 
} 

result = result.Skip(10) 
       .Take(5) 
       .ToList<MyTable>(); 
+1

他希望属性是一个动态字段 – Diego

+0

是的我改说不清楚 –

0

通常你会做到这一点:

.OrderBy(x => x.yourField) 

.OrderByDescending(x => x.yourField) 

,如果你需要你的领域是动态的,检查this答案

0

如果该字段通过为string(例如,当使用ObjectDataSource),你可以使用switch图吧:

var qry = context 
    .MyTable 
    .Where(x => x.Code > 5); 

switch(orderBy) { 
    case "MyField": qry = qry.OrderBy(r => r.MyField); break; 
    case "MyField DESC": qry = qry.OrderByDescending(r => r.MyField); break; 
} 

// By the way, ToList can infer the generic type if you don't 
// want to state it explicity 
var result = qry.Skip(10).Take(5).ToList(); 

查询至少有EF它是在SQL Server上执行的是不ToList之前执行,和。我承认switch有很多样板,但它确实相当可靠和快速。

+0

没有开关我想要更有活力的东西 –

3

您可以在扩展方法,它允许对LINQ语法使用反射:

public static IQueryable<TSource> OrderBy<TSource>(this IQueryable<TSource> source, string field, string direction) 
{ 
    string orderByMethod = (direction == "ASC") ? "OrderBy" : (direction == "DESC" ? "OrderByDescending" : null); 
    if(orderByMethod == null) throw new ArgumentException(); 

    var propertyInfo = typeof (TSource).GetProperty(field); 
    var entityParam = Expression.Parameter(typeof(TSource), "e"); 
    Expression columnExpr = Expression.Property(entityParam, propertyInfo); 
    LambdaExpression columnLambda = Expression.Lambda(columnExpr, entityParam); 

    MethodInfo orderByGeneric = typeof (Queryable).GetMethods().Single(m => m.Name == orderByMethod 
                && m.GetParameters().Count() == 2 
                && m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(IQueryable<>) 
                && m.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>)); 

    MethodInfo orderBy = orderByGeneric.MakeGenericMethod(new [] {typeof(TSource), propertyInfo.PropertyType}); 

    return (IQueryable<TSource>) orderBy.Invoke(null, new object[] { source, columnLambda }); 
} 

使用示例:

internal class SomeType 
{ 
    public string StringValue { get; set; } 
} 

IQueryable<SomeType> l = new List<SomeType> 
    { 
     new SomeType {StringValue = "bbbbb"}, 
     new SomeType {StringValue = "cccc"}, 
     new SomeType {StringValue = "aaaa"}, 
     new SomeType {StringValue = "eeee"}, 
    }.AsQueryable(); 

var asc = l.OrderBy("StringValue", "ASC"); 
var desc = l.OrderBy("StringValue", "DESC"); 

或者为你的例子:

context.MyTable 
     .Where(x => x.Code > 5) 
     .OrderBy(field, direction) 
     .Skip(10) 
     .Take(5) 
     .ToList<MyTable>(); 
1
void Main() { 
    // Ascending by some other property 
    CreateOrdering(item => item.SomeProperty, SortDirection.Ascending).Dump("Ascending order for SomeClass.SomeProperty"); 
    // Descending by some other property 
    CreateOrdering(item => item.SomeProperty, SortDirection.Descending).Dump("Descending order for SomeClass.SomeProperty"); 
    // Ascending by the Code property 
    CreateOrdering(item => item.Code, SortDirection.Ascending).Dump("Ascending order for SomeClass.Code"); 
    // Descending by the Code property 
    CreateOrdering(item => item.Code, SortDirection.Descending).Dump("Descending order for SomeClass.Code"); 
} 

// I reccomend not using bare strings, and instead use an enum 
public enum SortDirection { 
    Ascending = 0, 
    Descending = 1 
} 
// Define other methods and classes here 
public List<SomeClass> CreateOrdering<T>(Expression<Func<SomeClass, T>> field, SortDirection direction) { 
    // query does not get executed yet, because we have not enumerated it. 
    var query = context.MyTable 
     .Where(x => x.Code > 5); 

    if (direction.Equals(SortDirection.Ascending)) { 
     query = query.OrderBy (field); 
    } else { 
     query = query.OrderByDescending (field); 
    } 

    // query gets executed when the call ToList is made. 
    return query.Skip(10) 
       .Take(5) 
       .ToList(); 
} 

public static class context { 
    private static List<SomeClass> _MyTable = new List<SomeClass>() { 
     new SomeClass("A", 4), new SomeClass("B", 5), new SomeClass("C", 6), 
     new SomeClass("D", 7), new SomeClass("E", 8), new SomeClass("F", 9), 
     new SomeClass("G", 10), new SomeClass("H", 11), new SomeClass("I", 12), 
     new SomeClass("J", 13), new SomeClass("K", 14), new SomeClass("L", 15), 
     new SomeClass("M", 16), new SomeClass("N", 17), new SomeClass("O", 18) 
    }; 

    public static IQueryable<SomeClass> MyTable { 
     get { 
      return _MyTable.AsQueryable(); 
     } 
    } 
} 

public class SomeClass { 
    public SomeClass(string property, int code) { 
     this.SomeProperty = property; 
     this.Code = code; 
    } 

    public string SomeProperty { get; set; } 

    public int Code { get; set; } 
} 

Results of Execution in LINQPad

+1

就像我的回答,只是更好的实施和很好的例子。删除我的和+1给你。 – Heinzi

+0

哇,谢谢:D –